Skip to content

Desktop: task refresh fails with opaque persistence_failed; the real transcript error is discarded #5572

Description

@MoonOld

What happened

Refreshing a task in Maka Desktop fails with a generic toast and an opaque error code, and the real cause is discarded — so the failure cannot be diagnosed from the product's own diagnostics.

Toast:

  • Title: 刷新任务失败 (Could not refresh task)
  • Body: 任务内容暂时无法刷新,请稍后重试。

Main-process log (4 occurrences over ~25 min):

Error occurred in handler for 'sessions:transcript:open': RuntimeHostOperationError: Session transcript is unavailable
    at #acceptResponse (.../@maka/runtime-host/dist/client/connection.js:408:24)
    at #readResponses (.../@maka/runtime-host/dist/client/connection.js:368:37)
    at process.processTicksAndRejections (node:internal/process/task_queues:104:5) {
  operation: 'session.transcript.page',
  code: 'persistence_failed'
}

Why this is a diagnosability bug

packages/runtime-host/src/server/session-continuity-coordinator.ts, #readTranscriptPage(), funnels every unexpected throw from readSessionTranscriptPage() into one catch-all outcome:

} catch (error) {
  if (error instanceof TranscriptPageRequestError) {
    return { ok: false, error: { code: 'invalid_request', message: error.message } };
  }
  return { ok: false, error: { code: 'persistence_failed', message: 'Session transcript is unavailable' } };
}

Because the handler returns an outcome instead of throwing, the [runtime-host] unexpected <operation> failure: ... log in operation-dispatcher.ts (which is the only place that calls boundedFailureDiagnostic) never runs. As a result the underlying error is not recorded anywhere:

  • not in the Runtime Host log,
  • not in the desktop diagnostic report,
  • not in the Renderer (which only sees persistence_failed).

The Renderer then falls back to generic copy because the error carries no recognized classification (apps/desktop/src/renderer/app-shell-copy.tsclassifiedErrorFallbackcopy.errors.messageRefresh).

Failure candidates that all collapse into this one opaque code

packages/runtime-host/src/server/session-transcript-reader.ts throws, and each is swallowed by the catch-all above:

  • Durable RuntimeEvent transcript projection is incomplete (a hard read-model diagnostic) — most likely in this report
  • Session transcript Turn exceeds its message limit (> 4096 messages)
  • Session transcript Turn exceeds its byte limit (> 16 MiB)
  • Session transcript projection exceeds its presentation limit
  • Session transcript projection scan exceeds its capacity limit (> 16 MiB hidden-row scan)
  • any underlying storage read error

Note that several of these are deterministic: "please try again later" is wrong copy for them, since a retry will always fail.

How to reproduce

Not yet reduced to a minimal case — flagging the conditions instead:

  1. Run Maka Desktop (nightly) for several hours and work in a large task. In the reported instance the affected workspace store held ~28,851 runtime events for a single session (runtime.sqlite ~456 MB).
  2. Trigger a transcript refresh / reload on that task.
  3. The toast appears and sessions:transcript:open returns persistence_failed.

Environment

  • Maka: 0.2.0-dev.44.20260920 (packaged, nightly)
  • OS: macOS darwin 25.4.0 (arm64)
  • Electron 43.4.1 · Chrome 150.0.7871.224 · Node 24.18.1
  • Surface: Desktop
  • Source commit: 2da8a03
  • Storage health at the time: runtime.sqlite ~456 MB with integrity_check and quick_check both ok, 152 GiB disk free, Runtime Host ready → not corruption, not disk-full, not a host crash.

Logs / additional context

The full desktop diagnostic report is available; the transcript entries above are its only signal. Related but probably unrelated noise in the same report: a skills:listInvocablesession_archived failure ~6h earlier, and a MaxListenersExceededWarning (11 destroyed listeners on WebContents) ~3.7h earlier.

Suggested fixes

  1. Log the real error. In the non-TranscriptPageRequestError branch, emit boundedFailureDiagnostic(error) (plus session/subscription context) to the host log before returning the generic outcome.
  2. Separate transient from deterministic failures. Projection/limit violations are not retryable and should not reuse the "try again later" code or copy.
  3. Surface a typed, actionable error to the Renderer (e.g. transcript too large / needs repair) instead of the umbrella persistence_failed.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions