{"record":{"id":"6bb045014574e80a","repo":"can1357/oh-my-pi","slug":"omp-auth-broker-account-pool-file-contains-a-provi","errorCode":null,"errorMessage":"OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains a provider id with surrounding whitespace","messagePattern":"OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains a provider id with surrounding whitespace","errorType":"validation","errorClass":"AIError.ConfigurationError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/auth-broker/discover.ts","lineNumber":141,"sourceCode":"\ttry {\n\t\tparsed = await Bun.file(filePath).json();\n\t} catch (error) {\n\t\tthrow new AIError.ConfigurationError(`Unable to read OMP_AUTH_BROKER_ACCOUNT_POOL_FILE at ${filePath}`, {\n\t\t\tcause: error,\n\t\t});\n\t}\n\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new AIError.ConfigurationError(\"OMP_AUTH_BROKER_ACCOUNT_POOL_FILE must contain a JSON object\");\n\t}\n\n\tconst accountPool = new Map<string, ReadonlySet<string>>();\n\tfor (const [provider, value] of Object.entries(parsed)) {\n\t\tconst normalizedProvider = provider.trim();\n\t\tif (normalizedProvider.length === 0) {\n\t\t\tthrow new AIError.ConfigurationError(\"OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains an empty provider id\");\n\t\t}\n\t\tif (provider !== normalizedProvider) {\n\t\t\tthrow new AIError.ConfigurationError(\n\t\t\t\t\"OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains a provider id with surrounding whitespace\",\n\t\t\t);\n\t\t}\n\t\tif (!Array.isArray(value)) {\n\t\t\tthrow new AIError.ConfigurationError(\n\t\t\t\t`OMP_AUTH_BROKER_ACCOUNT_POOL_FILE entry for ${provider} must be an array of identity keys`,\n\t\t\t);\n\t\t}\n\t\tconst identities = new Set<string>();\n\t\tfor (const identity of value) {\n\t\t\tif (typeof identity !== \"string\" || identity.length === 0) {\n\t\t\t\tthrow new AIError.ConfigurationError(\n\t\t\t\t\t`OMP_AUTH_BROKER_ACCOUNT_POOL_FILE entry for ${provider} contains an invalid identity key`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (identity !== identity.trim()) {\n\t\t\t\tthrow new AIError.ConfigurationError(\n\t\t\t\t\t`OMP_AUTH_BROKER_ACCOUNT_POOL_FILE entry for ${provider} contains an identity key with surrounding whitespace`,","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/auth-broker/discover.ts#L123-L159","documentation":"Provider ids in the pool file must not have leading or trailing whitespace. The loader trims each key for the emptiness check but then requires the raw key to equal its trimmed form; \" openai\" or \"anthropic \" is rejected with this ConfigurationError. This catches hand-edited or machine-generated files where stray spaces would silently break provider matching.","triggerScenarios":"OMP_AUTH_BROKER_ACCOUNT_POOL_FILE has a provider key like \" openai\" or \"anthropic\\t\" (leading/trailing space or tab around the key).","commonSituations":"Manual JSON editing that introduced a stray space; templating that interpolated \"provider \" with a trailing space; generators joining strings with unintended separators.","solutions":["Edit the pool file and remove the leading/trailing whitespace from the offending key.","Run a check: `jq 'keys | map(select(. != (| . | trim)))' pool.json` (or compare keys to trimmed keys in a script) and fix all listed keys.","Fix the generating template/script so it trims provider ids before serializing."],"exampleFix":"// before (account-pool.json)\n{\n  \" openai \": [\"acc1\"]\n}\n\n// after\n{\n  \"openai\": [\"acc1\"]\n}","handlingStrategy":"validation","validationCode":"function validateNoWhitespaceKeys(pool: Record<string, unknown>): void {\n  for (const key of Object.keys(pool)) {\n    if (key !== key.trim()) {\n      throw new Error(`provider key has surrounding whitespace: ${JSON.stringify(key)}`);\n    }\n  }\n}","typeGuard":"function keysAreTrimmed(v: Record<string, unknown>): boolean {\n  return Object.keys(v).every((k) => k === k.trim());\n}","tryCatchPattern":"try {\n  const pool = await loadAuthBrokerAccountPool();\n} catch (err) {\n  if (err instanceof AIError.ConfigurationError && err.message.includes(\"surrounding whitespace\")) {\n    logger.error(\"pool file provider key has surrounding whitespace; strip it in the file\");\n  } else throw err;\n}","preventionTips":["Trim provider ids in any script that composes the pool file before serialization.","Validate keys in CI: compare Object.keys(pool) with their trimmed versions.","Avoid manual edits to machine-managed JSON; regenerate instead.","Watch for templating tools that append trailing spaces inside interpolated keys."],"tags":["configuration","json","validation","whitespace"],"backgroundTag":"schema-validation-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}