zylon-ai/private-gpt · error · ValueError
INVALID_REQUEST_ERROR
INVALID_REQUEST_ERROR
Error message
Failed to upload file to S3 for async ingestion
What it means
ValueError (mapped to INVALID_REQUEST_ERROR) raised in the async ingestion scheduler when upload_file_to_s3 returns a falsy URL after attempting to push binary ingest content to the configured temporary S3 bucket. The task is never dispatched to Celery — the request fails before scheduling.
Source
Thrown at private_gpt/components/ingestion/ingestion_scheduler.py:451
if ingest_body.ingest_body.input:
should_upload = (
not isinstance(ingest_body.ingest_body.input, UriArtifact)
or ingest_body.ingest_body.input.is_base64()
)
s3_helper = self._require_s3_helper()
if should_upload and s3_helper.is_available():
content = ingest_body.ingest_body.input.to_binary_content(
get_file_name(ingest_body.ingest_body.metadata)
)
object_name = str(uuid.uuid4())
s3_url = s3_helper.upload_file_to_s3(
filename=content.filename,
bytes_data=content.data.read(),
bucket_name=config.s3.temporary_bucket_name,
object_name=object_name,
)
if not s3_url:
raise ValueError("Failed to upload file to S3 for async ingestion")
ingest_body.ingest_body.metadata = {
**(ingest_body.ingest_body.metadata or {}),
"file_name": content.filename,
}
ingest_body.ingest_body.input = UriArtifact(value=s3_url)
result = dispatch_task(
task_name=PARSE_TASK_NAME,
args=(ingest_body,),
queue=config.scheduler.ingestion.celery_queue,
)
task_id = result.task_id
if not isinstance(task_id, str):
raise ValueError("ingest_async did not return a valid task_id")
return task_id
def ingest(self, ingest_body: IngestBody) -> IngestResponse:
"""Parse then store synchronously, blocking until both complete."""View on GitHub (pinned to 4a030776a3)
Solutions
- Verify config.s3 settings: endpoint URL, credentials, and temporary_bucket_name all correct and the bucket exists.
- Test the helper directly: s3_helper.upload_file_to_s3(...) on a small file and inspect why it returns None (check its internal error swallowing).
- Check IAM/MinIO policy grants s3:PutObject on the temporary bucket.
- If S3 is not intended for this deployment, disable the should_upload path so content is passed inline.
Defensive patterns
Strategy: try-catch
Validate before calling
if should_upload:
if not s3_helper.is_available():
raise RuntimeError('S3 helper reports unavailable')
if not config.s3.temporary_bucket_name:
raise RuntimeError('s3.temporary_bucket_name not configured') Try / catch
try:
task_id = scheduler.ingest_async(body)
except ValueError as e:
if 'Failed to upload file to S3' in str(e):
return api_error(503, 'Storage backend temporarily unavailable; retry shortly') Prevention
- Add a startup connectivity check that PUTs a tiny object to temporary_bucket_name.
- Alert when upload_file_to_s3 returns falsy — it swallows the underlying boto error; log it inside the helper.
When it happens
Trigger: Submitting an async ingest request with should_upload true and s3_helper.is_available() true, but the S3 upload silently fails (helper returns None/empty instead of raising) — e.g. wrong credentials, unreachable endpoint, missing temporary_bucket_name bucket.
Common situations: Misconfigured S3 credentials or endpoint in config.s3; the temporary bucket does not exist or is in another region; MinIO not running in local dev; IAM policy without s3:PutObject.
Related errors
- S3 storage provider requires bucket_name
- Invalid system item in list: {item}
- Chunk size must be greater than 0.
- API base URL and poll interval must be provided in async mod
- Local storage provider requires local_root_path
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/6ad170758f25a45d.
Report an issue: GitHub.