{"record":{"id":"a0bc8ab94cf873a6","repo":"can1357/oh-my-pi","slug":"omp-auth-broker-account-pool-file-contains-an-empt","errorCode":null,"errorMessage":"OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains an empty provider id","messagePattern":"OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains an empty provider id","errorType":"validation","errorClass":"AIError.ConfigurationError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/auth-broker/discover.ts","lineNumber":138,"sourceCode":"\tif (!filePath) return undefined;\n\n\tlet parsed: unknown;\n\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}","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/auth-broker/discover.ts#L120-L156","documentation":"Each top-level key of the pool object is a provider id. If a key trims to the empty string (i.e. the key is empty or entirely whitespace), the loader throws this ConfigurationError. Empty provider ids cannot be matched against any real provider and indicate a malformed pool file.","triggerScenarios":"OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains a JSON object with a key that is \"\" or whitespace-only (e.g. \"\": [...] or \"   \": [...]).","commonSituations":"Template/template-substitution failure that left an empty provider placeholder key; programmatic generation using an undefined variable as the key; copy-paste of a JSON snippet with an accidental empty key.","solutions":["Open the pool file and remove the empty or whitespace-only key (JSON linters/`jq keys` help spot it).","Fix the generator so the provider id variable is populated before writing the file.","Validate the file before use: `jq 'keys | map(select(ltrimstr(\" \") | length == 0))'` should list nothing."],"exampleFix":"// before (account-pool.json)\n{\n  \"\": [\"acc1\"]\n}\n\n// after\n{\n  \"openai\": [\"acc1\"]\n}","handlingStrategy":"validation","validationCode":"function validateProviderKeys(pool: Record<string, unknown>): void {\n  for (const key of Object.keys(pool)) {\n    if (key.trim().length === 0) {\n      throw new Error(`pool file contains empty provider key: ${JSON.stringify(key)}`);\n    }\n  }\n}","typeGuard":"function hasNoEmptyProviderKeys(v: Record<string, unknown>): boolean {\n  return Object.keys(v).every((k) => k.trim().length > 0);\n}","tryCatchPattern":"try {\n  const pool = await loadAuthBrokerAccountPool();\n} catch (err) {\n  if (err instanceof AIError.ConfigurationError && err.message.includes(\"empty provider id\")) {\n    logger.error(\"pool file has an empty provider key; remove it and regenerate\");\n  } else throw err;\n}","preventionTips":["Run `jq 'keys' pool.json` and eyeball for empty/whitespace keys before deploying.","Fix template substitution so provider placeholders are always populated.","Add a pre-write assertion in the pool generator that every key is non-empty after trim.","Lint the pool file in CI with a tiny JSON schema requiring non-empty property names."],"tags":["configuration","json","validation","auth-broker"],"backgroundTag":"schema-validation-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}