stablyai/orca · warning · LinearWriteFailure

unconfirmed

unconfirmed

Error message

Linear relation mutation could not be confirmed.

What it means

Thrown by runRelationMutation when the underlying mutation fails with a duplicate_id classification. Because relation creates carry no caller-supplied id, a duplicate may actually be a successful concurrent add that Linear rejects as duplicate — so the operation cannot be confirmed either way. Encoded as LinearWriteFailure kind 'unconfirmed' with the original error as cause; isAuthError errors are rethrown unchanged.

Source

Thrown at src/main/linear/issue-relation-mutation.ts:76

      { id: relationId }
    )
  )
  if (raw.data?.issueRelationDelete?.success !== true) {
    throw new LinearWriteFailure('failed', 'Linear relation removal failed')
  }
}

async function runRelationMutation<T>(mutation: () => Promise<T>): Promise<T> {
  try {
    return await mutation()
  } catch (error) {
    if (isAuthError(error)) {
      throw error
    }
    const failure = classifyLinearWriteFailure(error)
    if (failure.kind === 'duplicate_id') {
      // Why: relation creates have no caller-supplied id, so a duplicate can be a concurrent add.
      throw new LinearWriteFailure(
        'unconfirmed',
        'Linear relation mutation could not be confirmed.',
        error
      )
    }
    throw failure
  }
}

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Treat kind 'unconfirmed' as a probable success: refetch the issue's relations to confirm whether the relation now exists.
  2. Debounce/disable the link button until the in-flight mutation settles.
  3. Make the create idempotent client-side by checking existing relations before re-submitting.
  4. Do not blindly retry — that can create a third duplicate.

Example fix

// before
await createLinearIssueRelation(client, input)
// after
try { await createLinearIssueRelation(client, input) }
catch (e) {
  if (e instanceof LinearWriteFailure && e.kind === 'unconfirmed') {
    return await findRelation(input.issueId, input.relatedIssueId, input.type)
  }
  throw e
}
Defensive patterns

Strategy: fallback

Validate before calling

if (await findRelation(input.issueId, input.relatedIssueId, input.type)) return existingRelation

Type guard

function isLinearRelationUnconfirmed(e: unknown): e is LinearWriteFailure {
  return e instanceof Error && (e as LinearWriteFailure).name === 'LinearWriteFailure' && (e as LinearWriteFailure).kind === 'unconfirmed'
}

Try / catch

try { return await createLinearIssueRelation(client, input) }
catch (e) {
  if (e instanceof LinearWriteFailure && e.kind === 'unconfirmed') return await findRelation(input.issueId, input.relatedIssueId, input.type) ?? null
  throw e
}

Prevention

When it happens

Trigger: Two concurrent createLinearIssueRelation calls for the same issue pair (e.g. user double-submits, or two app tabs), causing Linear to return a duplicate_id error on the second. The first may have succeeded.

Common situations: Double-click on a 'Link issue' button. Optimistic UI re-firing after a network hiccup. Multi-window app usage.

Related errors


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