{"record":{"id":"4e9b104c4802147e","repo":"can1357/oh-my-pi","slug":"flickr-getsizes-response-did-not-include-sizes","errorCode":null,"errorMessage":"flickr getSizes response did not include sizes","messagePattern":"flickr getSizes response did not include sizes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/blob-broker/uploaders-image-hosts.ts","lineNumber":251,"sourceCode":"\tfor (const [option, parameter] of mappings) {\n\t\tconst value = optionString(config, option);\n\t\tif (value) fields[parameter] = value;\n\t}\n\treturn fields;\n}\n\nfunction flickrPhotoId(xml: string): string {\n\tconst status = /<rsp\\b[^>]*\\b(?:stat|status)=[\"']([^\"']+)[\"']/i.exec(xml)?.[1];\n\tif (status && status !== \"ok\") throw new Error(\"flickr rejected the upload\");\n\tconst photoId = /<photoid\\b[^>]*>([^<]+)<\\/photoid>/i.exec(xml)?.[1]?.trim();\n\tif (!photoId) throw new Error(\"flickr response did not include a photo ID\");\n\treturn photoId;\n}\n\nfunction largestFlickrSource(payload: Record<string, unknown>): string {\n\tif (payload.stat !== \"ok\") throw new Error(\"flickr getSizes request failed\");\n\tconst sizes = nestedRecord(payload, \"sizes\", \"flickr\").size;\n\tif (!Array.isArray(sizes)) throw new Error(\"flickr getSizes response did not include sizes\");\n\tfor (let index = sizes.length - 1; index >= 0; index--) {\n\t\tconst size = sizes[index];\n\t\tif (size && typeof size === \"object\" && !Array.isArray(size)) {\n\t\t\tconst source = (size as Record<string, unknown>).source;\n\t\t\tif (typeof source === \"string\" && source) return directUrl(source, \"flickr\");\n\t\t}\n\t}\n\tthrow new Error(\"flickr getSizes response did not include a direct image URL\");\n}\n\nfunction createFlickrUploader(config: DestinationRuntimeConfig): BlobUploader {\n\tconst credentials: FlickrOAuthCredentials = {\n\t\tconsumerKey: requireCredential(config, \"apiKey\"),\n\t\tconsumerSecret: requireCredential(config, \"apiSecret\"),\n\t\ttoken: requireCredential(config, \"oauthToken\"),\n\t\ttokenSecret: requireCredential(config, \"oauthTokenSecret\"),\n\t};\n\tconst uploadFields = flickrUploadFields(config);","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/blob-broker/uploaders-image-hosts.ts#L233-L269","documentation":"largestFlickrSource() throws this when the getSizes response reports stat 'ok' but the sizes array is missing or not an array. The uploader relies on the sizes list to pick the largest available image URL.","triggerScenarios":"Flickr returned a successful envelope whose sizes.sizes.size field is absent, null, or a single object instead of an array — e.g. an unexpected API schema, empty photo record, or a differently-shaped response from a proxy.","commonSituations":"Flickr API schema drift, an empty/placeholder photo record, middleware rewriting the JSON, or calling getSizes on a photo still being processed.","solutions":["Log the getSizes JSON payload and confirm the shape (rsp.sizes.size should be an array)","Retry — the photo may not have been fully processed yet right after upload","Check for API version changes in Flickr's flickr.photos.getSizes documentation","Normalize a single-object size response to an array before the Array.isArray check"],"exampleFix":"// before\nconst sizes = nestedRecord(payload, \"sizes\", \"flickr\").size;\nif (!Array.isArray(sizes)) throw new Error(\"flickr getSizes response did not include sizes\");\n// after\nconst rawSizes = nestedRecord(payload, \"sizes\", \"flickr\").size;\nconst sizes = Array.isArray(rawSizes) ? rawSizes : rawSizes ? [rawSizes] : null;\nif (!sizes) throw new Error(\"flickr getSizes response did not include sizes\");","handlingStrategy":"type-guard","validationCode":"const sizes = payload?.sizes?.size;\nif (!Array.isArray(sizes) || sizes.length === 0) throw new Error(\"getSizes returned no sizes yet; retry later\");","typeGuard":"function hasSizes(payload: unknown): payload is { sizes: { size: unknown[] } } {\n\tconst p = payload as Record<string, any> | null;\n\treturn !!p && Array.isArray(p.sizes?.size);\n}","tryCatchPattern":"try {\n\tconst src = largestFlickrSource(payload);\n} catch (err) {\n\tif (err instanceof Error && err.message.includes(\"did not include sizes\")) {\n\t\t// normalize single-object size or retry after processing delay\n\t}\n\tthrow err;\n}","preventionTips":["Normalize single-object size responses to arrays before consuming","Retry shortly after upload while renditions generate","Log and version-check the getSizes schema in tests","Validate responses with a narrow type guard before indexing"],"tags":["flickr","api","response-parsing","schema"],"backgroundTag":"api-response-schema-mismatch","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}