Skip to content

fix(desktop): apps page empty due to OmiAppCapability decoding failure#6385

Merged
beastoin merged 2 commits into
mainfrom
fix/desktop-apps-decode-6380
Apr 7, 2026
Merged

fix(desktop): apps page empty due to OmiAppCapability decoding failure#6385
beastoin merged 2 commits into
mainfrom
fix/desktop-apps-decode-6380

Conversation

@beastoin
Copy link
Copy Markdown
Collaborator

@beastoin beastoin commented Apr 7, 2026

Summary

  • Root cause: /v1/app-capabilities returns objects without a description field, but OmiAppCapability struct had description: String as required. Since getAppCapabilities() runs concurrently with getAppsV2() in AppProvider.fetchApps(), the decode failure causes the entire try await to fail, showing "No apps found".
  • Fix: Added custom init(from:) decoder to OmiAppCapability using decodeIfPresent for both title and description, defaulting to empty string.
  • Also: Reduced getAppsV2 default limit from 100 to 50 to match backend max.

v0.11.241 still has this bug — Apps page shows "No apps found" in production. This fix was verified locally with a test bundle.

Evidence

  • Before (Omi Beta v0.11.241): Apps page shows "No apps found" + Decoding error - key 'description' not found in logs
  • After (test-6380 with fix): Apps page loads all apps (Imports, Exports grid)

Test plan

🤖 Generated with Claude Code

beastoin and others added 2 commits April 7, 2026 13:23
The /v1/app-capabilities endpoint returns objects without a `description`
field, but OmiAppCapability had it as required. Since getAppCapabilities()
runs concurrently with getAppsV2() in AppProvider.fetchApps(), the decode
failure causes the entire try-await to fail, showing "No apps found".

Also reduces getAppsV2 default limit from 100 to 50 to match backend max.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 7, 2026

Greptile Summary

This PR fixes a production bug where the Apps page showed "No apps found" because /v1/app-capabilities returns objects without a description field, causing OmiAppCapability decoding to throw. Since getAppCapabilities() runs concurrently with getAppsV2() in a single try await tuple, one decode failure aborted the entire fetch. The fix adds a custom init(from:) using decodeIfPresent for title and description, defaulting to \"\".

Confidence Score: 5/5

Safe to merge — targeted fix for a confirmed production crash with no regressions introduced.

Single-file change with a correct, well-scoped decoding fix. The only finding is a P2 style note about a redundant CodingKeys enum with no behavioral impact. Encoding conformance is unaffected because the explicit CodingKeys enum causes Swift to synthesize encode(to:) correctly.

No files require special attention.

Important Files Changed

Filename Overview
desktop/Desktop/Sources/APIClient.swift Adds custom Decodable init to OmiAppCapability using decodeIfPresent for title/description; reduces getAppsV2 limit from 100 to 50

Sequence Diagram

sequenceDiagram
    participant AP as AppProvider.fetchApps()
    participant AC as APIClient
    participant BE as Backend

    AP->>+AC: async let getAppsV2()
    AP->>+AC: async let getAppCategories()
    AP->>+AC: async let getAppCapabilities()

    AC->>BE: GET /v2/apps
    AC->>BE: GET /v1/app-categories
    AC->>BE: GET /v1/app-capabilities

    BE-->>AC: apps JSON
    BE-->>AC: categories JSON
    BE-->>AC: capabilities JSON (missing description field)

    Note over AC: Before fix: decode throws → entire try await fails
    Note over AC: After fix: decodeIfPresent defaults to empty string → success

    AC-->>-AP: OmiAppsV2Response
    AC-->>-AP: [OmiAppCategory]
    AC-->>-AP: [OmiAppCapability]

    AP->>AP: Update UI state
Loading

Reviews (1): Last reviewed commit: "Revert getAppsV2 limit to 100 — backend ..." | Re-trigger Greptile

Comment on lines +2930 to 2933
enum CodingKeys: String, CodingKey {
case id, title, description
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Redundant CodingKeys enum

All three case names (id, title, description) exactly match their property names, so Swift's synthesized CodingKeys would be identical. This can be removed with no behavioral change.

Suggested change
enum CodingKeys: String, CodingKey {
case id, title, description
}
}
}

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@beastoin
Copy link
Copy Markdown
Collaborator Author

beastoin commented Apr 7, 2026

Test Results — PR #6385 verified on Mac Mini M4

Build

  • Branch: fix/desktop-apps-decode-6380
  • Named test bundle: pr6385.app (com.omi.pr6385)
  • Build: xcrun swift build -c debugclean, 17s incremental

Results

Area Status Details
Apps page PASS 334 apps loaded (5 featured, 29 integrations, 100 chat, 100 summary, 100 notifications)
Tasks (action items) PASS 6+11 items synced, "Test PR 6272 desktop tools" displayed
Goals PASS 4 goals displayed on Dashboard
Decoding errors ZERO No description not found, no key/type mismatches

Comparison: Omi Beta v0.11.241 (WITHOUT this fix)

[06:22:33.156] [error] Decoding error - key 'description' not found: No value associated with key CodingKeys(stringValue: "description", intValue: nil) ("description")
[06:22:33.613] [error] Failed to fetch apps: The data couldn't be read because it is missing.

Apps page shows "No apps found" because /v1/app-capabilities returns {id, title} without description, causing OmiAppCapability decode to fail, which kills the entire AppProvider.fetchApps() concurrent await.

Logs from pr6385 test bundle (WITH this fix)

[13:39:14.695] [app] GoalStorage: Synced 4 goals from server
[13:39:14.749] [app] ActionItemStorage: Synced 11 task action items from backend
[13:39:14.762] [app] ActionItemStorage: Synced 6 task action items from backend
[13:39:16.073] [app] Fetched 334 apps via v2: 5 featured, 29 integrations, 100 chat, 100 summary, 100 notifications
[13:39:16.073] [perf] DATA LOAD: Apps (1821.5ms)

Zero [error] lines related to decoding.

Screenshots

Dashboard — Tasks + Goals working:
Dashboard

Apps page — full grid loaded:
Apps

Tasks page — action items parsed:
Tasks

@beastoin
Copy link
Copy Markdown
Collaborator Author

beastoin commented Apr 7, 2026

lgtm

@beastoin beastoin merged commit 94b4b42 into main Apr 7, 2026
2 checks passed
@beastoin beastoin deleted the fix/desktop-apps-decode-6380 branch April 7, 2026 13:46
@beastoin
Copy link
Copy Markdown
Collaborator Author

beastoin commented Apr 7, 2026

v0.11.242 Live Verification — PASS

Omi Beta updated to v0.11.242 via Sparkle on Mac Mini M4.

Results

Area Status Details
Apps page PASS Full grid loaded (Imports + Exports) — no more "No apps found"
Tasks (action items) PASS 11 items synced from backend
Goals PASS 4 goals displayed on Dashboard
description not found error GONE Zero occurrences
Failed to fetch apps error GONE Zero occurrences

Logs (v0.11.242 session)

[07:21:33.133] [app] ActionItemStorage: Synced 11 task action items from backend
[07:21:36.467] [app] Screen capture test: SUCCESS

Zero [error] lines related to apps or goals decoding.

Screenshots (Omi Beta v0.11.242)

Dashboard — title bar shows v0.11.242, Tasks + Goals working:
Dashboard

Apps page — full grid loaded:
Apps

Minor: new TaskDedup error (pre-existing, unrelated to this PR)

[07:21:33.740] [error] Decoding error - key 'action_items' not found
[07:21:33.744] [app] TaskDedup: Failed to fetch staged tasks

/v1/staged-tasks returns {"items": ...} but ActionItemsListResponse now expects action_items after PR #6380's CodingKey change. Non-critical (dedup is background-only), but should be fixed separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant