stablyai/orca · error · Error

Concrete Linear workspace ID is required

Error message

Concrete Linear workspace ID is required

What it means

Thrown by normalizeConcreteWorkspaceId (in projects.ts) when the workspaceId is not a non-empty string or equals 'all'. Project functions take LinearConcreteWorkspaceId, which must be a single real workspace, not the multi-workspace 'all' selector. It is a plain Error, not a LinearWriteFailure.

Source

Thrown at src/main/linear/projects.ts:534

}

function coalesce<T>(key: string, load: () => Promise<T>, force = false): Promise<T> {
  const existing = inFlight.get(key) as Promise<T> | undefined
  if (existing && !force) {
    return existing
  }
  const promise = load().finally(() => {
    if (inFlight.get(key) === promise) {
      inFlight.delete(key)
    }
  })
  inFlight.set(key, promise)
  return promise
}

function normalizeConcreteWorkspaceId(workspaceId: unknown): LinearConcreteWorkspaceId {
  if (typeof workspaceId !== 'string' || !workspaceId.trim() || workspaceId === 'all') {
    throw new Error('Concrete Linear workspace ID is required')
  }
  return workspaceId.trim()
}

function workspaceError(entry: LinearClientForWorkspace, error: unknown): LinearWorkspaceError {
  if (isAuthError(error)) {
    return {
      workspaceId: entry.workspace.id,
      workspaceName: entry.workspace.organizationName,
      type: 'auth',
      message: 'Linear authentication expired for this workspace.'
    }
  }

  const record = error as { name?: string; message?: string; status?: number; response?: unknown }
  const message = record.message || 'Linear request failed.'
  const status =
    typeof record.status === 'number'

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Resolve to a single workspace id before calling project functions.
  2. If selection is 'all', iterate connected workspaces and call once per concrete id.
  3. Validate the value is a non-empty string other than 'all' at the boundary.

Example fix

// before
await listProjectsByExactName(name, workspaceSelection)
// after
if (workspaceSelection === 'all') throw new Error('Select one workspace')
await listProjectsByExactName(name, workspaceSelection)
Defensive patterns

Strategy: validation

Validate before calling

function assertConcreteWorkspaceId(workspaceId: unknown): asserts workspaceId is string {
  if (typeof workspaceId !== 'string' || !workspaceId.trim() || workspaceId === 'all')
    throw new Error('A concrete Linear workspace id is required')
}

Type guard

function isConcreteWorkspaceId(workspaceId: unknown): workspaceId is string {
  return typeof workspaceId === 'string' && workspaceId.trim().length > 0 && workspaceId !== 'all'
}

Try / catch

try { await listProjectsByExactName(name, workspaceId as LinearConcreteWorkspaceId) }
catch (e) { if (e instanceof Error && /concrete.*workspace/i.test(e.message)) { pickConcreteWorkspace(); return } throw e }

Prevention

When it happens

Trigger: Passing undefined/null/'all'/'' (or a non-string) to a project function (listProjectsByExactName, getProject, etc.) that calls normalizeConcreteWorkspaceId.

Common situations: Caller forwarded a LinearWorkspaceSelection value that can legally be 'all' into a concrete-only API; UI selection defaulted to 'all' and was not narrowed.

Related errors


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