Neuroloom

Reference

Error Catalog

Neuroloom's API returns two error shapes depending on when the error family was added. Both carry a stable code string a client can branch on — check code, not the human-readable message text, which may change without notice.

Legacy shape (most existing errors): {"detail": "...", "code": "..."}.

Current shape (workspace resolution errors, this page's subject, and the standard for new error families going forward): a nested {"error": {...}} envelope with no detail wrapper at all.

This page documents the three workspace-resolution errors introduced by OAuth workspace simplification. They fire when the server can't determine which workspace an authenticated request should operate on.


Why these errors exist

An OAuth-authenticated request no longer carries a workspace inside its access token — the token proves who you are, not which workspace you're working in. Every request picks a workspace fresh: send X-Workspace-Id to name one explicitly, or omit it and let the server auto-resolve when you belong to exactly one workspace. These three errors cover the cases where the server can't make that call for you. See Per-Project Workspace Routing for the full mental model.

Note

API key authentication is unaffected — API keys are workspace-scoped by their key binding and never hit these errors.


workspace_not_specified

HTTP status: 400 Bad Request

Raised when an OAuth-authenticated request omits X-Workspace-Id and the caller belongs to two or more active workspaces. The server has no way to guess which one you mean.

{
  "error": {
    "code": "workspace_not_specified",
    "message": "You belong to 3 workspaces. Specify which one with the X-Workspace-Id header, or update your MCP/API client config to include it.",
    "request_id": "5f9e1c2a-...",
    "workspaces": [
      { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "personal-blog" },
      { "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "name": "company-api" },
      { "id": "c3d4e5f6-a7b8-9012-cdef-123456789012", "name": "oss-library" }
    ],
    "hints": {
      "claude_code_plugin": "Run `/neuroloom:init` (or restart your session) — the plugin re-resolves and writes X-Workspace-Id to .mcp.json automatically once your membership is unambiguous.",
      "manual_mcp_config": "Add \"X-Workspace-Id\": \"<id>\" to the headers field in your MCP client config, using one of the workspace IDs listed above.",
      "rest_api": "Send the X-Workspace-Id header on every request, set to one of the workspace IDs listed above."
    },
    "setup_url": "https://neuroloom.dev/docs/guides/multi-workspace"
  }
}

Fix by client:

ClientFix
Claude Code pluginRun /neuroloom:init or restart your session — the plugin re-resolves automatically once membership is unambiguous and writes the result to .mcp.json.
Manual MCP config (Cursor, VS Code, Windsurf)Add an X-Workspace-Id header to your client's config, set to one of the IDs in workspaces. See Per-Project Workspace Routing.
REST API / cURLSend X-Workspace-Id on every request, set to one of the IDs in workspaces.

no_workspace_membership

HTTP status: 400 Bad Request

Raised when an OAuth-authenticated request omits X-Workspace-Id and the caller belongs to zero active workspaces. This is a 400, not a 403 — the server is only ever reporting the authenticated caller's own membership count, never a third party's, so there's no cross-tenant information to protect by using 403's unified-denial convention.

{
  "error": {
    "code": "no_workspace_membership",
    "message": "You don't belong to any workspace yet. Create one at the Neuroloom dashboard, then retry — the X-Workspace-Id header isn't needed until you have at least one membership.",
    "request_id": "5f9e1c2a-...",
    "workspaces": [],
    "hints": {
      "claude_code_plugin": "Create a workspace at the Neuroloom dashboard, then restart your session — the plugin will pick it up automatically.",
      "manual_mcp_config": "Create a workspace at the Neuroloom dashboard, then set the X-Workspace-Id header to its ID in your MCP client config.",
      "rest_api": "Create a workspace at the Neuroloom dashboard before calling any workspace-scoped endpoint."
    },
    "setup_url": "https://neuroloom.dev/docs/guides/multi-workspace"
  }
}

workspaces is always empty for this error — there's nothing to list.

Fix by client:

ClientFix
Claude Code pluginCreate a workspace at app.neuroloom.dev/settings/workspace, then restart your session — the plugin picks it up automatically.
Manual MCP configCreate a workspace at the dashboard, then set X-Workspace-Id to its ID in your client config.
REST API / cURLCreate a workspace at the dashboard before calling any workspace-scoped endpoint.

This also fires from the OAuth consent screen — a zero-workspace user is blocked from completing consent (the approve branch only; denying consent always succeeds regardless of membership count).


invalid_workspace_id

HTTP status: 400 Bad Request

Raised when X-Workspace-Id is present but either isn't a valid UUID, or names a workspace the caller isn't an active member of. Both cases return the same code and status — the response never discloses whether a malformed value or a well-formed-but-foreign one caused the failure, which keeps this consistent with the rest of the API's non-enumeration behavior.

{
  "error": {
    "code": "invalid_workspace_id",
    "message": "The X-Workspace-Id header is not valid — it must be a UUID matching one of your active workspace memberships.",
    "request_id": "5f9e1c2a-...",
    "workspaces": [
      { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "personal-blog" }
    ],
    "hints": {
      "claude_code_plugin": "Run `/neuroloom:init` (or restart your session) to let the plugin re-resolve and overwrite the invalid X-Workspace-Id value.",
      "manual_mcp_config": "Fix the X-Workspace-Id header in your MCP client config — it must exactly match one of the workspace IDs listed above.",
      "rest_api": "Send a valid X-Workspace-Id header, set to one of the workspace IDs listed above."
    },
    "setup_url": "https://neuroloom.dev/docs/guides/multi-workspace"
  }
}

workspaces lists the caller's own active memberships — fetched specifically for this error, not carried over from an auto-resolve check that didn't run (the header was present, so auto-resolve never fires).

Fix by client:

ClientFix
Claude Code pluginRun /neuroloom:init or restart your session — the plugin re-resolves and overwrites the invalid value.
Manual MCP configFix the X-Workspace-Id header in your client config so it exactly matches one of the IDs in workspaces.
REST API / cURLSend a valid X-Workspace-Id header, set to one of the IDs in workspaces.

Reading the envelope

Every field in the error object is stable and safe to parse programmatically:

FieldTypeDescription
codestringStable machine-readable identifier. Branch on this, not on message.
messagestringHuman-readable explanation, self-sufficient without a docs lookup — it names the membership count and the fix.
request_idstring (UUID)Matches the response's X-Request-ID header. Include this when filing a support request.
workspacesarray of {id, name}The caller's own active workspace memberships, scoped to this specific error. Empty for no_workspace_membership.
hintsobjectPer-client next-action text, keyed by claude_code_plugin, manual_mcp_config, rest_api.
setup_urlstring (URL)Links to Per-Project Workspace Routing.
Tip

Filing a bug or support request about one of these errors? Include the request_id — it lets Neuroloom's team find the exact request in server logs.


Ready to get started?

Start building with Neuroloom for free.

Start Building Free