stablyai/orca · error · Error

Unexpected Linear tasks response

Error message

Unexpected Linear tasks response

What it means

extractLinearIssueReadItems received a result from the Linear RPC that is neither a bare array nor an { items: [...] } envelope. The function accepts unknown (it is the raw RpcSuccess.result) and narrows through two shapes before throwing. This is a contract/shape mismatch: the desktop runtime returned a Linear payload the mobile parser does not recognize.

Source

Thrown at mobile/src/tasks/linear-mobile-issue-read.ts:38

type LinearIssueReadEnvelope = {
  items?: unknown
}

export function extractLinearIssueReadItems(result: unknown): LinearMobileIssue[] {
  if (Array.isArray(result)) {
    return result as LinearMobileIssue[]
  }

  if (
    result &&
    typeof result === 'object' &&
    Array.isArray((result as LinearIssueReadEnvelope).items)
  ) {
    return (result as { items: LinearMobileIssue[] }).items
  }

  throw new Error('Unexpected Linear tasks response')
}

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Log the actual result shape (keys + typeof) when this throws so the envelope can be added to the narrower.
  2. Extend extractLinearIssueReadItems to accept the new envelope (e.g. { nodes } or { data: { issues } }).
  3. Degrade to an empty list with a visible warning rather than crashing the whole search panel.
  4. Pin mobile and desktop to compatible versions until the contract is updated.

Example fix

// before
if (
  result &&
  typeof result === 'object' &&
  Array.isArray((result as LinearIssueReadEnvelope).items)
) {
  return (result as { items: LinearMobileIssue[] }).items
}
throw new Error('Unexpected Linear tasks response')

// after — accept additional envelope shapes and degrade safely
if (result && typeof result === 'object') {
  const obj = result as Record<string, unknown>
  const list = obj.items ?? obj.nodes ?? (obj.data as { issues?: unknown[] })?.issues
  if (Array.isArray(list)) return list as LinearMobileIssue[]
}
return [] // graceful degradation instead of a crash
Defensive patterns

Strategy: type-guard

Type guard

function isLinearResultArray(r: unknown): r is LinearMobileIssue[] {
  return Array.isArray(r)
}

function isLinearEnvelope(r: unknown): r is { items: LinearMobileIssue[] } {
  return !!r && typeof r === 'object' && Array.isArray((r as any).items)
}

Try / catch

try {
  const items = extractLinearIssueReadItems(result)
} catch (e) {
  console.error('Linear shape mismatch', Object.keys(result ?? {}))
  return [] // graceful degradation
}

Prevention

When it happens

Trigger: The host's linear.searchIssues/linear.listIssues returned a paginated envelope without an items key (e.g. { nodes: [...] } or { data: { issues: [...] } }); the runtime wrapped the result in an extra layer; a version mismatch introduced a new envelope; the runtime returned an error-shaped object that still passed isRpcResponse.

Common situations: Desktop runtime updated its Linear integration to a new GraphQL response shape; mobile and desktop are on mismatched versions; the Linear workspace returned an empty/edge-case object; a relay in the middle altered the payload.

Related errors


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