{"record":{"id":"c4502f06f5cf0e05","repo":"HeyPuter/puter","slug":"bad-request-c4502f","errorCode":"bad_request","errorMessage":"`source` is required","messagePattern":"`source` is required","errorType":"validation","errorClass":"HttpError","httpStatus":400,"severity":"warning","filePath":"src/backend/drivers/ai-ocr/OCRDriver.ts","lineNumber":188,"sourceCode":"\n    async recognize(args: RecognizeArgs) {\n        if (args.test_mode) return sampleResponse();\n\n        const provider = this.#resolveProvider(args);\n        if (!provider)\n            throw new HttpError(500, 'No OCR provider configured', {\n                legacyCode: 'internal_error',\n            });\n\n        const actor = Context.get('actor');\n        if (!actor)\n            throw new HttpError(401, 'Authentication required', {\n                legacyCode: 'unauthorized',\n            });\n\n        const input = args.source ?? args.file;\n        if (!input)\n            throw new HttpError(400, '`source` is required', {\n                legacyCode: 'bad_request',\n            });\n\n        const loaded = await loadFileInput(\n            this.stores,\n            this.services.fs,\n            actor,\n            input,\n            { acceptWebInput: true },\n        );\n\n        if (provider === 'aws-textract') {\n            if (!this.#awsConfig)\n                throw new HttpError(500, 'AWS credentials not configured', {\n                    legacyCode: 'internal_error',\n                });\n            return this.#textractRecognize(loaded, actor);\n        }","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/drivers/ai-ocr/OCRDriver.ts#L170-L206","documentation":"The OCR driver requires a document to process, passed via either args.source or args.file. If both are falsy (undefined, null, empty string), the driver has nothing to send to Textract or Mistral and rejects the request immediately.","triggerScenarios":"Calling recognize() with neither source nor file in the args object; passing an empty object {}; passing undefined for both fields due to destructuring errors or form submission issues.","commonSituations":"The client SDK call omits the file/source parameter; a file upload form submitted without selecting a file; the source field is set but to a falsy value (0, false, empty string) that the nullish coalescing (??) and logical-or fallback don't distinguish from missing.","solutions":["Provide a valid source (URL, file path, FS UID, or base64 data URI) or file object in the recognize() call.","Validate on the client side that a file is selected before submitting.","Check that the SDK method used (puter.ai.ocr or puter.ai.txtrec) receives the file parameter correctly."],"exampleFix":"// before — no source provided\nconst result = await driver.recognize({ provider: 'aws-textract' });\n\n// after — provide a source\nconst result = await driver.recognize({\n  source: 'https://example.com/document.pdf',\n  provider: 'aws-textract',\n});","handlingStrategy":"validation","validationCode":"function validateOcrSource(args: { source?: unknown; file?: unknown }): unknown {\n  const input = args.source ?? args.file;\n  if (!input) {\n    throw new Error('`source` or `file` is required for OCR');\n  }\n  return input;\n}\n// Use before calling recognize:\nconst input = validateOcrSource(args);","typeGuard":"function hasOcrInput(args: { source?: unknown; file?: unknown }): boolean {\n  return Boolean(args.source ?? args.file);\n}","tryCatchPattern":null,"preventionTips":["Always provide either source or file when calling recognize().","Validate file uploads on the client side to ensure a file was selected.","Check that the SDK method used passes the file parameter correctly."],"tags":["ocr","input-validation","source","missing-parameter"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}