stablyai/orca · error · Error

envelope.error.message

Error message

envelope.error.message

What it means

The gitlab.listWorkItems RPC succeeded at transport level (response.ok === true) but the result envelope carries a non-not_found error: { items, error?: { type?, message } }. The code throws only when envelope.error.type exists and is not 'not_found'. This is the GitLab provider surfacing an auth, permission, or connection error as a soft envelope field rather than an RPC failure.

Source

Thrown at mobile/src/tasks/smart-source-search-requests.ts:66

  query: string,
  state: MrStateFilter
): Promise<GitLabWorkItem[]> {
  const response = await client.sendRequest('gitlab.listWorkItems', {
    repo: `id:${repoId}`,
    state,
    page: 1,
    perPage: GITLAB_PER_PAGE,
    query: query.trim() || undefined
  })
  if (!response.ok) {
    throw new Error(response.error.message)
  }
  const envelope = (response as RpcSuccess).result as {
    items: GitLabWorkItem[]
    error?: { type?: string; message: string }
  }
  if (envelope.error?.type && envelope.error.type !== 'not_found') {
    throw new Error(envelope.error.message)
  }
  return (envelope.items ?? []).map((item) => ({ ...item, repoId }))
}

export async function searchLinearIssues(
  client: RpcClient,
  query: string,
  linearWorkspaceId: string | null | undefined
): Promise<LinearIssue[]> {
  const trimmed = query.trim()
  const response = trimmed
    ? await client.sendRequest('linear.searchIssues', {
        query: trimmed,
        limit: LINEAR_LIMIT,
        workspaceId: linearWorkspaceId ?? undefined
      })
    : await client.sendRequest('linear.listIssues', {
        // Empty query lists the viewer's assigned issues, matching desktop's

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Inspect envelope.error.type to distinguish auth errors from transient ones.
  2. For auth-type errors, surface 'Re-authorize GitLab on your computer' and return [].
  3. For transient types, return [] and auto-retry on next query input.
  4. Always preserve not_found as an empty result (the existing guard) — do not throw for it.

Example fix

// before
if (envelope.error?.type && envelope.error.type !== 'not_found') {
  throw new Error(envelope.error.message)
}

// after — classify auth vs transient, degrade instead of throwing
if (envelope.error?.type && envelope.error.type !== 'not_found') {
  if (envelope.error.type === 'auth') {
    return [] // UI shows 'Re-authorize GitLab' banner
  }
  throw new Error(envelope.error.message)
}
Defensive patterns

Strategy: type-guard

Type guard

function isGitLabSoftError(r: unknown): r is { type: string; message: string } {
  const env = r as { error?: { type?: string; message: string } }
  return !!env.error?.type && env.error.type !== 'not_found'
}

Try / catch

try {
  const items = await searchGitLabItems(client, repoId, query, state)
} catch (e) {
  // envelope.error carries the provider reason
  if (e.message.includes('auth')) {
    showGitLabReauthBanner()
  }
  return []
}

Prevention

When it happens

Trigger: The host's GitLab token lacks scope for the project; GitLab returned a 401/403 that the runtime normalized into the envelope; the GitLab instance is reachable but the API version is unsupported; a transient GitLab 5xx was wrapped as a generic error type.

Common situations: Host GitLab token scope reduced after the search was opened; GitLab project moved to private; self-hosted GitLab API version mismatch; GitLab instance overloaded returning 5xx.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/f98159e6ece5aa40. Report an issue: GitHub.