decolua/9router · error · Error

No Zed organization selected

Error message

No Zed organization selected

What it means

fetchZedLlmToken needs an organizationId before it can request an LLM token. It resolves it from options/config, then falls back to calling fetchZedAuthenticatedUser and resolving from the user info. If no organization can be resolved from either source, it throws "No Zed organization selected".

Source

Thrown at open-sse/shared/zedAuth.js:261

  const token = credentials?.accessToken || credentials?.apiKey || "";
  return `${userId}:${organizationId || "default"}:${token.slice(-16)}`;
}

function zedModelCacheKey(credentials) {
  const psd = credentials?.providerSpecificData || {};
  const org = psd.organizationId || psd.defaultOrganizationId || "default";
  const token = credentials?.accessToken || credentials?.apiKey || "";
  return `${psd.userId || "unknown"}:${org}:${token.slice(-16)}`;
}

export async function fetchZedLlmToken(credentials, options = {}) {
  const config = options.config || {};
  let organizationId = options.organizationId || resolveZedOrganizationId(credentials);
  if (!organizationId) {
    const userInfo = await fetchZedAuthenticatedUser(credentials, options);
    organizationId = resolveZedOrganizationId(credentials, userInfo);
  }
  if (!organizationId) throw new Error("No Zed organization selected");

  const cacheKey = zedUserCacheKey(credentials, organizationId);
  const cached = llmTokenCache.get(cacheKey);
  if (!options.forceRefresh && cached && cached.expiresAt > Date.now()) return cached.token;

  const headers = {
    "Content-Type": "application/json",
    Accept: "application/json",
    Authorization: buildZedUserAuthHeader(credentials),
  };
  const systemId = getSystemId(credentials);
  if (systemId) headers[ZED_HEADERS.systemId] = systemId;

  const data = await fetchJson(
    zedUrl(config, "cloudBaseUrl", "/client/llm_tokens", ZED_CLOUD_BASE_URL),
    {
      method: "POST",
      headers,

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Set providerSpecificData.organizationId (or defaultOrganizationId) on the Zed credential explicitly.
  2. Pass options.organizationId directly to fetchZedLlmToken to bypass resolution.
  3. Verify the account actually belongs to an organization by inspecting the /client/users/me response and use the correct id field.
  4. Check resolveZedOrganizationId against your stored userInfo shape — normalizeOrganizationId accepts string, [id], or {id}; other shapes fail.

Example fix

// before
await fetchZedLlmToken(credentials); // no org anywhere
// after
await fetchZedLlmToken(credentials, { organizationId: "org_abc123" });
Defensive patterns

Strategy: validation

Validate before calling

const orgId = credentials?.providerSpecificData?.organizationId
  || credentials?.providerSpecificData?.defaultOrganizationId;
if (!orgId) {
  // resolve from /client/users/me first or surface org-picker UI before calling fetchZedLlmToken
}

Type guard

const hasOrg = (c) => Boolean(c?.providerSpecificData?.organizationId || c?.providerSpecificData?.defaultOrganizationId);

Try / catch

try {
  const token = await fetchZedLlmToken(credentials, options);
} catch (e) {
  if (e.message === "No Zed organization selected") {
    // show organization picker / verify account membership
  } else throw e;
}

Prevention

When it happens

Trigger: Calling fetchZedLlmToken when neither credentials.providerSpecificData.organizationId/defaultOrganizationId nor the /client/users/me response yields an organization id — e.g. the Zed account belongs to no organization, or userInfo has an unexpected shape.

Common situations: Fresh Zed account with no org membership; enterprise SSO account where org ids live in a different field; stale cached user info; user never picked a default org in the dashboard config.

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/b8094cb4d567b2ff. Report an issue: GitHub.