can1357/oh-my-pi · error · AIError.OAuthError

Z.ai key provisioning failed: no organization/project on acc

Error message

Z.ai key provisioning failed: no organization/project on account

What it means

mintZaiApiKey lists the account's organizations and picks the default (or first) org and project. If no organization or project yields a non-empty organizationId/projectId, key provisioning cannot proceed and OAuthError is thrown. The account simply has no provisioned org/project hierarchy to attach an API key to.

Source

Thrown at packages/ai/src/registry/oauth/zai.ts:174

 * `getCustomerInfo` → find/create the OMP-named key → obtain its secret →
 * return `${apiKey}.${secretKey}` (the 49-char durable key).
 */
async function mintZaiApiKey(oauthAccessToken: string, fetchImpl: FetchImpl): Promise<string> {
	const bizToken = await businessLogin(oauthAccessToken, fetchImpl);
	const auth = { Authorization: `Bearer ${bizToken}` };

	const customer = unwrapEnvelope(
		await getJson(`${BIZ_BASE}/api/biz/customer/getCustomerInfo`, auth, fetchImpl),
		"customer lookup",
	) as { organizations?: ZaiOrganization[] } | undefined;
	const orgs = Array.isArray(customer?.organizations) ? customer.organizations : [];
	const org = orgs.find(o => o?.isDefault) ?? orgs[0];
	const projects = Array.isArray(org?.projects) ? org.projects : [];
	const project = projects.find(p => p?.isDefault) ?? projects[0];
	const organizationId = trimmedString(org?.organizationId);
	const projectId = trimmedString(project?.projectId);
	if (!organizationId || !projectId) {
		throw new AIError.OAuthError("Z.ai key provisioning failed: no organization/project on account", {
			kind: "token-exchange",
			provider: "zai",
		});
	}

	const keysUrl = `${BIZ_BASE}/api/biz/v1/organization/${organizationId}/projects/${projectId}/api_keys`;
	const existing = asKeyArray(unwrapEnvelope(await getJson(keysUrl, auth, fetchImpl), "api key list")).find(
		key => key.name === KEY_NAME,
	);
	const keyRecord =
		existing ??
		(unwrapEnvelope(await postJson(keysUrl, { name: KEY_NAME }, auth, fetchImpl), "api key create") as
			| Record<string, unknown>
			| undefined);

	const apiKey = trimmedString(keyRecord?.apiKey);
	if (!apiKey) {
		throw new AIError.OAuthError("Z.ai key provisioning returned no apiKey", {

View on GitHub (pinned to 9690622007)

Solutions

  1. Log into the Z.ai console and create an organization and a project before running the login flow.
  2. Re-run the OAuth login after provisioning — the listing will then resolve org/project.
  3. If you are not an org admin, ask an admin to grant your account project membership.
  4. Inspect the raw org list response to rule out a schema change; update the library if Z.ai renamed fields.

Example fix

// before
const biz = await mintZaiApiKey(oauthToken, fetch); // throws on fresh account
// after
await ensureZaiOrgAndProject(oauthToken); // creates org/project via console/API if missing
const biz = await mintZaiApiKey(oauthToken, fetch);
Defensive patterns

Strategy: validation

Validate before calling

const orgs = await listZaiOrgs(token, fetch);
const org = orgs.find(o => o.isDefault) ?? orgs[0];
if (!org?.organizationId || !(org.projects ?? []).length) throw new Error("Z.ai account has no organization/project; create one in the console first");

Type guard

function hasProvisioning(org: unknown): org is { organizationId: string; projects: { projectId: string }[] } {
  const o = org as { organizationId?: unknown; projects?: unknown };
  return typeof o?.organizationId === "string" && o.organizationId.length > 0 && Array.isArray(o.projects) && o.projects.length > 0;
}

Try / catch

try { return await mintZaiApiKey(token, fetch); }
catch (e) { if (e instanceof AIError.OAuthError && e.message.includes("no organization/project")) return guideUserToConsole(); throw e; }

Prevention

When it happens

Trigger: Org list returns empty array; the only org has no projects array; ids are present but empty/non-string so trimmedString returns undefined.

Common situations: Brand-new Z.ai account that never created an organization/project; enterprise account where project creation is restricted to admins; API returning a changed shape (projects nested differently).

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/4eecf44e6585f83c. Report an issue: GitHub.