{"record":{"id":"5514e1b3d50c167f","repo":"moeru-ai/airi","slug":"output-does-not-contain-a-recognizable-image-url","errorCode":null,"errorMessage":"Output does not contain a recognizable image URL.","messagePattern":"Output does not contain a recognizable image URL\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/stage-tamagotchi/src/main/services/airi/widgets/providers/replicate.ts","lineNumber":167,"sourceCode":"        if (typeof first === 'object' && first !== null && 'url' in first && typeof (first as any).url === 'function') {\n          imageUrl = (first as any).url().href\n        }\n        // Case 2: Object with url property as a string\n        else if (typeof first === 'object' && first !== null && 'url' in first && typeof (first as any).url === 'string') {\n          imageUrl = (first as any).url\n        }\n        // Case 3: Simple string (the URL itself)\n        else if (typeof first === 'string') {\n          imageUrl = first\n        }\n\n        if (imageUrl && (imageUrl.startsWith('http') || imageUrl.startsWith('data:'))) {\n          log.log(`[Replicate] EXTRACTED IMAGE: ${imageUrl.startsWith('data:') ? 'DATA_URL' : imageUrl}`)\n          this.updateStatus(jobId, { status: 'succeeded', progress: 100, imageUrl })\n        }\n        else {\n          log.error(`[Replicate] Failed to extract URL from output: ${JSON.stringify(first)}`)\n          throw new Error('Output does not contain a recognizable image URL.')\n        }\n      }\n      else {\n        throw new Error('Replicate returned an empty output array.')\n      }\n    }\n    catch (error: any) {\n      const errorMessage = error.message || (typeof error === 'object' ? JSON.stringify(error) : String(error))\n      log.error(`[Replicate] Generation Failed for ${jobId}: ${errorMessage}`)\n      this.updateStatus(jobId, {\n        status: 'failed',\n        error: errorMessage,\n        actionLabel: `Error: ${errorMessage.slice(0, 50)}${errorMessage.length > 50 ? '...' : ''}`,\n      })\n    }\n    finally {\n      // Clean up callback and job result after completion to prevent memory leaks\n      setTimeout(() => {","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/apps/stage-tamagotchi/src/main/services/airi/widgets/providers/replicate.ts#L149-L185","documentation":"Thrown after iterating the output items when the first element is an object that lacks a callable `url`, is not a string, and does not match any of the three recognized shapes (FileUpload with .url(), object with .url string, or raw URL string). The extracted imageUrl is undefined or does not start with http/data:.","triggerScenarios":"Replicate SDK upgraded to a version that returns a new output envelope shape (e.g. a PaginatedResponse, a different FileUpload API, or a prediction object instead of bare outputs); model returns a metadata object instead of an image reference.","commonSituations":"replicate npm package version bump changed run() return shape; model returns output as an object with a nested URL under a non-standard key; the model is not an image model and returns text/JSON.","solutions":["Inspect the logged `[Replicate] Failed to extract URL from output:` line to see the actual object shape, then add a matching extraction branch.","Pin or upgrade the replicate npm package deliberately and re-test; the SDK output contract changed across major versions.","Verify the model is an image-output model (flux, sd-xl, etc.), not a generic model.","Add a branch for `first.output` or `first.url` as a string property in addition to the callable check."],"exampleFix":"// before\nif (typeof first === 'object' && first !== null && 'url' in first && typeof (first as any).url === 'function') {\n  imageUrl = await (first as any).url()\n}\n\n// after\nif (typeof first === 'object' && first !== null) {\n  if (typeof (first as any).url === 'function') imageUrl = await (first as any).url()\n  else if (typeof (first as any).url === 'string') imageUrl = (first as any).url\n  else if (typeof (first as any).output === 'string') imageUrl = (first as any).output\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isFileUploadWithUrl(item: unknown): boolean {\n  return typeof item === 'object' && item !== null\n    && 'url' in item\n    && (typeof (item as any).url === 'function' || typeof (item as any).url === 'string')\n}\nfunction isUrlString(item: unknown): item is string {\n  return typeof item === 'string' && /^https?:|^data:/.test(item)\n}","tryCatchPattern":"try {\n  // extraction logic\n} catch (e) {\n  log.error('Replicate output shape unrecognized', { first })\n  throw e\n}","preventionTips":["Pin the replicate npm version and re-test extraction after upgrades.","Add extraction branches for every SDK output shape you encounter, with tests.","Log the unrecognized object so future shape changes are diagnosable."],"tags":["replicate","version-compat","artistry","parsing"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}