{"record":{"id":"dada74a4df5fe572","repo":"can1357/oh-my-pi","slug":"context-omitted-field","errorCode":null,"errorMessage":"${context} omitted ${field}","messagePattern":"(.+?) omitted (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/blob-broker/uploaders-object-storage.ts","lineNumber":438,"sourceCode":"\t\t\tconst publicUrl = publicBaseUrl ? publicObjectUrl(publicBaseUrl, key) : url.toString();\n\t\t\treturn publication(destination, uploadRequest, publicUrl, {\n\t\t\t\tremoteId: key,\n\t\t\t\tdelete: { method: \"DELETE\", url: url.toString(), headers: deleteHeaders },\n\t\t\t});\n\t\t},\n\t};\n}\n\nfunction asRecord(value: unknown, context: string): Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(`${context} returned an invalid JSON object`);\n\t}\n\treturn value as Record<string, unknown>;\n}\n\nfunction requiredStringField(value: unknown, field: string, context: string): string {\n\tconst result = asRecord(value, context)[field];\n\tif (typeof result !== \"string\" || result.length === 0) throw new Error(`${context} omitted ${field}`);\n\treturn result;\n}\n\nfunction optionalStringField(value: unknown, field: string): string | undefined {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined;\n\tconst result = (value as Record<string, unknown>)[field];\n\treturn typeof result === \"string\" ? result : undefined;\n}\n\nasync function sha1Hex(bytes: Uint8Array): Promise<string> {\n\tconst digest = new Uint8Array(await crypto.subtle.digest(\"SHA-1\", strictBytes(bytes)));\n\tlet result = \"\";\n\tfor (const byte of digest) result += byte.toString(16).padStart(2, \"0\");\n\treturn result;\n}\n\nasync function b2Json(\n\tconfig: DestinationRuntimeConfig,","sourceCodeStart":420,"sourceCodeEnd":456,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/blob-broker/uploaders-object-storage.ts#L420-L456","documentation":"requiredStringField extracts a required string field from an already-validated JSON object and throws `${context} omitted ${field}` when the field is missing, not a string, or an empty string. It is used for B2 fields like accountId, authorizationToken, apiUrl, bucketId, and bucketType, so an incomplete API response surfaces with a message naming the exact stage and field.","triggerScenarios":"A B2 API response object (authorization, bucket record, upload target) lacks a required field or contains it as null/empty — e.g. b2_authorize_account returning partial JSON, or a bucket record missing bucketId/bucketType because the API version changed.","commonSituations":"B2 account restricted so authorization omits allowed-capability fields; API response schema drift after a B2 API update; intermittent truncated response parsed as valid JSON with absent fields; wrong endpoint returning a minimal error object with 200 status.","solutions":["Log the full JSON body from the failing stage (`context` tells you which) and inspect which field is absent.","Re-run b2_authorize_account manually (curl) to confirm the API returns the expected fields for your account/key.","Verify the application key has permissions for the operation; restricted keys can yield reduced responses.","Check for a B2 API version mismatch and pin/update the /b2api/v2/ calls accordingly."],"exampleFix":"// before\n// assuming authorization always has apiUrl\nconst bucketUrl = authorization.apiUrl + \"/file/\" + bucketName;\n// after\nconst apiUrl = requiredStringField(authorization, \"apiUrl\", \"Backblaze B2 authorization\"); // throws with a clear message if absent\nconst bucketUrl = apiUrl + \"/file/\" + bucketName;","handlingStrategy":"validation","validationCode":"function assertFields(obj: Record<string, unknown>, fields: string[], context: string): void {\n  for (const f of fields) {\n    const v = obj[f];\n    if (typeof v !== \"string\" || v.length === 0) throw new Error(`${context} omitted ${f}`);\n  }\n}\n// assertFields(authJson, [\"accountId\", \"authorizationToken\", \"apiUrl\"], \"B2 authorization\");","typeGuard":"function hasStringField(v: unknown, field: string): v is Record<string, string> {\n  return typeof v === \"object\" && v !== null && typeof (v as Record<string, unknown>)[field] === \"string\"\n    && ((v as Record<string, unknown>)[field] as string).length > 0;\n}","tryCatchPattern":"try {\n  const target = await b2UploadTarget(config, authorization, bucketId);\n} catch (err) {\n  if (err instanceof Error && / omitted \\w+$/.test(err.message)) {\n    logger.error(\"B2 response missing field; re-authorize and check key capabilities\", { err });\n  } else throw err;\n}","preventionTips":["re-authorize B2 before long-running sessions; tokens and derived fields can go stale","use application keys with capabilities matching all operations (listBuckets, writeFiles)","pin/verify the B2 API version in endpoint URLs","log full JSON bodies on field-extraction failures to detect schema drift"],"tags":["object-storage","b2","api-response","validation"],"backgroundTag":"missing-api-response-field","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}