{"record":{"id":"444a59f920423157","repo":"zylon-ai/private-gpt","slug":"file-input-requires-valid-base64-encoded-content","errorCode":null,"errorMessage":"File input requires valid base64 encoded content","messagePattern":"File input requires valid base64 encoded content","errorType":"validation","errorClass":"ValueError","httpStatus":422,"severity":"error","filePath":"private_gpt/server/utils/artifact_input.py","lineNumber":73,"sourceCode":"\n    def to_binary(self) -> BinaryIO:\n        \"\"\"Convert to BinaryIO (legacy method).\"\"\"\n        return self.to_binary_content().data\n\n\nclass FileArtifact(Artifact):\n    \"\"\"Input for base64 encoded files.\"\"\"\n\n    type: Literal[\"file\"] = Field(\n        default=\"file\", description=\"Input type discriminator\"\n    )\n    value: str = Field(..., description=\"Base64 encoded file content\")\n\n    @field_validator(\"value\")\n    @classmethod\n    def validate_base64(cls, v: str) -> str:\n        if not _is_valid_base64(v):\n            raise ValueError(\"File input requires valid base64 encoded content\")\n        return v\n\n    def extract_filename(self, fallback_name: str | None = None) -> str:\n        return fallback_name or \"uploaded_file\"\n\n    def to_binary_content(self, filename: str | None = None) -> BinaryContent:\n        decoded = base64.b64decode(self.value)\n        extracted_filename = self.extract_filename(filename)\n        return BinaryContent(io.BytesIO(decoded), extracted_filename)\n\n\nclass UriArtifact(Artifact):\n    \"\"\"Input for remote URIs.\"\"\"\n\n    type: Literal[\"uri\"] = Field(default=\"uri\", description=\"Input type discriminator\")\n    value: str = Field(..., description=\"URI to download from\")\n\n    def extract_filename(self, fallback_name: str | None = None) -> str:","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/server/utils/artifact_input.py#L55-L91","documentation":"Pydantic field_validator error on FileArtifact.value: the string must pass _is_valid_base64 before the model is accepted. The API accepts inline files only as base64-encoded content, and any malformed encoding (wrong alphabet, bad padding, embedded whitespace/newlines not tolerated by the check) is rejected at request-validation time.","triggerScenarios":"POSTing a chat/context request with {\"type\": \"file\", \"value\": \"<raw bytes or plain text>\"}; base64 with missing '=' padding; base64url characters ('-', '_') if the validator uses standard alphabet validation; strings containing data-URI prefixes like 'data:text/plain;base64,...' or stray whitespace/newlines depending on _is_valid_base64's strictness.","commonSituations":"Frontends passing the raw file contents or a File object's toString(); copying base64 from JWTs (base64url) or URLs; data-URI prefixes left on drag-and-drop payloads; text editors stripping the final '=' padding; line-wrapped PEM-style base64 pasted as-is.","solutions":["Encode before sending: in JS `btoa(text)` / `await fileToBase64(file)`; in Python `base64.b64encode(data).decode()`.","Strip any 'data:...;base64,' prefix before submitting: `value.split(',').pop()`.","If the source is base64url (JWTs, signed URLs), convert: replace '-'->'+', '_'->'/', and re-pad to a multiple of 4 with '='.","Remove newlines/whitespace: `value.replace(/\\s/g, '')`."],"exampleFix":"// before\n{ type: 'file', value: rawFileText }\n// after\n{ type: 'file', value: btoa(rawFileText) }  // or await blobToBase64(fileBlob)","handlingStrategy":"validation","validationCode":"function toBase64Payload(input: string): string {\n  const cleaned = input.replace(/^data:[^,]*;base64,/, '').replace(/\\s+/g, '');\n  if (!/^[A-Za-z0-9+/]*={0,2}$/.test(cleaned)) throw new Error('not base64');\n  return cleaned.padEnd(Math.ceil(cleaned.length / 4) * 4, '=');\n}","typeGuard":"const isValidBase64 = (v: string): boolean =>\n  /^[A-Za-z0-9+/]*={0,2}$/.test(v) && v.length % 4 === 0;","tryCatchPattern":null,"preventionTips":["Always encode at the boundary: FileReader.readAsDataURL + strip prefix, or base64.b64encode server-side.","Never pass raw file contents with type 'file'.","Convert base64url (JWT-derived) values to standard base64 before submitting."],"tags":["base64","pydantic","validation","file-upload","api"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}