{"record":{"id":"05bc77113e8ee9a2","repo":"can1357/oh-my-pi","slug":"backblaze-b2-bucket-listing-omitted-buckets","errorCode":null,"errorMessage":"Backblaze B2 bucket listing omitted buckets","messagePattern":"Backblaze B2 bucket listing omitted buckets","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/blob-broker/uploaders-object-storage.ts","lineNumber":505,"sourceCode":"\t\tauthorizationToken: requiredStringField(value, \"authorizationToken\", \"Backblaze B2 authorization\"),\n\t\tapiUrl: requiredStringField(value, \"apiUrl\", \"Backblaze B2 authorization\"),\n\t\tdownloadUrl: requiredStringField(value, \"downloadUrl\", \"Backblaze B2 authorization\"),\n\t};\n}\n\nasync function findB2Bucket(\n\tconfig: DestinationRuntimeConfig,\n\tauthorization: B2Authorization,\n\tbucketName: string,\n): Promise<B2Bucket> {\n\tconst value = await b2Json(\n\t\tconfig,\n\t\t`${authorization.apiUrl}/b2api/v2/b2_list_buckets`,\n\t\tauthorization.authorizationToken,\n\t\t{ accountId: authorization.accountId, bucketName },\n\t);\n\tconst buckets = asRecord(value, \"Backblaze B2 bucket listing\").buckets;\n\tif (!Array.isArray(buckets)) throw new Error(\"Backblaze B2 bucket listing omitted buckets\");\n\tfor (const candidate of buckets) {\n\t\tif (optionalStringField(candidate, \"bucketName\") !== bucketName) continue;\n\t\treturn {\n\t\t\tbucketId: requiredStringField(candidate, \"bucketId\", \"Backblaze B2 bucket\"),\n\t\t\tbucketName,\n\t\t\tbucketType: requiredStringField(candidate, \"bucketType\", \"Backblaze B2 bucket\"),\n\t\t};\n\t}\n\tthrow new Error(`Backblaze B2 bucket not found: ${bucketName}`);\n}\n\nasync function b2UploadTarget(\n\tconfig: DestinationRuntimeConfig,\n\tauthorization: B2Authorization,\n\tbucketId: string,\n): Promise<B2UploadTarget> {\n\tconst value = await b2Json(\n\t\tconfig,","sourceCodeStart":487,"sourceCodeEnd":523,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/blob-broker/uploaders-object-storage.ts#L487-L523","documentation":"When resolving a B2 bucket by name, the code calls b2_list_buckets and reads the `buckets` field of the response; if that field is missing or not an array, it throws this error because the listing cannot be iterated to find the bucket. This indicates the B2 API responded but not with the expected bucket-listing envelope.","triggerScenarios":"b2_list_buckets responds with JSON that has no `buckets` array — e.g. an error object returned with a 200-ish status, an authorization token scoped such that the response shape differs, or an API/proxy issue returning a different payload.","commonSituations":"Expired/reviled authorization token used for the listing call; hitting the wrong apiUrl (stale authorization after token rotation); B2 service degradation returning an error envelope; account with API access but buckets listing disabled by key capabilities.","solutions":["Re-authorize with b2_authorize_account and retry the listing with the fresh apiUrl/authorizationToken.","Log the raw b2_list_buckets response body to see whether an error message replaced the buckets array.","Verify the application key's capabilities include listBuckets and access to the target bucket.","Check the B2 status page / retry in case of transient service issues."],"exampleFix":"// before\n// reusing a stale authorization for list_buckets\nconst value = await b2Call(authorization.apiUrl, ...);\n// after\nconst authorization = await authorizeB2(config); // refresh token + apiUrl first\nconst value = await b2Call(authorization.apiUrl, ...);","handlingStrategy":"retry","validationCode":null,"typeGuard":"function isBucketListing(v: unknown): v is { buckets: unknown[] } {\n  return typeof v === \"object\" && v !== null && Array.isArray((v as Record<string, unknown>).buckets);\n}","tryCatchPattern":"try {\n  const bucket = await findB2Bucket(config, authorization, bucketName);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"omitted buckets\")) {\n    const fresh = await authorizeB2(config); // refresh token, then retry once\n    return findB2Bucket(config, fresh, bucketName);\n  } else throw err;\n}","preventionTips":["refresh b2_authorize_account when listing calls fail with shape errors","monitor B2 status before assuming a config problem","keep authorization objects short-lived; do not cache across token rotations","log the raw list_buckets body to distinguish error envelopes from shape changes"],"tags":["object-storage","b2","api-response","network"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}