zylon-ai/private-gpt · error · ValueError
File input requires valid base64 encoded content
Error message
File input requires valid base64 encoded content
What it means
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.
Source
Thrown at private_gpt/server/utils/artifact_input.py:73
def to_binary(self) -> BinaryIO:
"""Convert to BinaryIO (legacy method)."""
return self.to_binary_content().data
class FileArtifact(Artifact):
"""Input for base64 encoded files."""
type: Literal["file"] = Field(
default="file", description="Input type discriminator"
)
value: str = Field(..., description="Base64 encoded file content")
@field_validator("value")
@classmethod
def validate_base64(cls, v: str) -> str:
if not _is_valid_base64(v):
raise ValueError("File input requires valid base64 encoded content")
return v
def extract_filename(self, fallback_name: str | None = None) -> str:
return fallback_name or "uploaded_file"
def to_binary_content(self, filename: str | None = None) -> BinaryContent:
decoded = base64.b64decode(self.value)
extracted_filename = self.extract_filename(filename)
return BinaryContent(io.BytesIO(decoded), extracted_filename)
class UriArtifact(Artifact):
"""Input for remote URIs."""
type: Literal["uri"] = Field(default="uri", description="Input type discriminator")
value: str = Field(..., description="URI to download from")
def extract_filename(self, fallback_name: str | None = None) -> str:View on GitHub (pinned to 4a030776a3)
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, '')`.
Example fix
// before
{ type: 'file', value: rawFileText }
// after
{ type: 'file', value: btoa(rawFileText) } // or await blobToBase64(fileBlob) Defensive patterns
Strategy: validation
Validate before calling
function toBase64Payload(input: string): string {
const cleaned = input.replace(/^data:[^,]*;base64,/, '').replace(/\s+/g, '');
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(cleaned)) throw new Error('not base64');
return cleaned.padEnd(Math.ceil(cleaned.length / 4) * 4, '=');
} Type guard
const isValidBase64 = (v: string): boolean =>
/^[A-Za-z0-9+/]*={0,2}$/.test(v) && v.length % 4 === 0; Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Provide SKILL.md either in files or skill_md
- 'oneOf' must be an array of schemas
- 'anyOf' must be an array of schemas
- 'allOf' must be an array of schemas
- Schema must define a 'type' field
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/444a59f920423157.
Report an issue: GitHub.