{"record":{"id":"047e42600cef44f0","repo":"stablyai/orca","slug":"failed-047e42","errorCode":"failed","errorMessage":"Not connected to Linear","messagePattern":"Not connected to Linear","errorType":"error_code","errorClass":"LinearWriteFailure","httpStatus":null,"severity":"error","filePath":"src/main/linear/issue-relation-write.ts","lineNumber":33,"sourceCode":"} from './issue-context-raw'\nimport { createLinearIssueRelation, deleteLinearIssueRelation } from './issue-relation-mutation'\nimport { LinearWriteFailure } from './issues'\n\nconst RELATION_WRITE_READ_CAP = 250\n\ntype RelationDirection = 'outbound' | 'inbound'\n\nexport async function writeIssueRelation(params: {\n  issue: LinearIssueRelationWriteResult['issue']\n  relatedIssue: LinearIssueRelationWriteResult['relatedIssue']\n  relationship: LinearIssueRelationship\n  operation: 'add' | 'remove'\n  workspaceId: string\n  signal?: AbortSignal\n}): Promise<LinearIssueRelationWriteResult> {\n  const entry = getClients(params.workspaceId)[0]\n  if (!entry) {\n    throw new LinearWriteFailure('failed', 'Not connected to Linear')\n  }\n  await acquire()\n  try {\n    const client = params.signal\n      ? new (loadLinearSdk().LinearClient)({ apiKey: entry.apiKey, signal: params.signal })\n      : entry.client\n    const existing = await findExistingRelation(client, params)\n    if (params.operation === 'add' && existing) {\n      return result(params, existing, true)\n    }\n    if (params.operation === 'remove' && !existing) {\n      return result(params, absentRelation(params), true)\n    }\n    if (params.operation === 'remove' && existing) {\n      await deleteLinearIssueRelation(client, existing.id)\n      return result(params, existing, false)\n    }\n    const created = await createLinearIssueRelation(client, relationCreateInput(params))","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/linear/issue-relation-write.ts#L15-L51","documentation":"Thrown by writeIssueRelation when getClients(params.workspaceId)[0] is undefined, i.e. no Linear client matches the requested workspace. The library requires a connected (token-loaded) workspace before any relation mutation. It fails fast with kind='failed' rather than silently no-oping.","triggerScenarios":"Calling writeIssueRelation with a workspaceId whose token is missing, expired, undecryptable, or that was never registered in workspace state. Also when workspaceId refers to a workspace id that has since been disconnected.","commonSituations":"User opened the agent flow before completing Linear OAuth, the saved token failed CredentialDecryption, or the workspace was disconnected between when the relation task was queued and when it ran.","solutions":["Verify Linear connection via getLinearStatus(); if not connected, prompt the user through connect/selectWorkspace.","Confirm params.workspaceId matches a connected workspace id in getWorkspaceState().workspaces.","If running from an agent loop, gate relation writes on a connected-workspace precondition before enqueueing.","Check for credential/decrypt errors and trigger a fresh token load."],"exampleFix":"// before\nconst res = await writeIssueRelation({ issue, relatedIssue, relationship, operation: 'add', workspaceId })\n// after\nconst entry = getClients(workspaceId)[0]\nif (!entry) throw new Error(`Linear workspace ${workspaceId} is not connected; cannot write relation`)\nconst res = await writeIssueRelation({ issue, relatedIssue, relationship, operation: 'add', workspaceId, signal })","handlingStrategy":"validation","validationCode":"import { getClients } from './client'\nconst entry = getClients(params.workspaceId)[0]\nif (!entry) throw new Error(`Workspace ${params.workspaceId} not connected; cannot write relation`)","typeGuard":"import { LinearWriteFailure } from './issues'\nfunction isNotConnectedFailure(e: unknown): boolean {\n  return e instanceof LinearWriteFailure && e.kind === 'failed' && e.message === 'Not connected to Linear'\n}","tryCatchPattern":"try {\n  await writeIssueRelation(params)\n} catch (e) {\n  if (isNotConnectedFailure(e)) { /* prompt connect, do not retry */ }\n  else throw e\n}","preventionTips":["Gate relation writes behind a getLinearStatus() connected check.","Pass the same workspace id recorded in workspace state, not a display name.","Re-derive the workspace id right before the call rather than caching it long-term."],"tags":["linear","authentication","workspace","relation","precondition"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}