odysseus-dev/odysseus · error · ValueError
Referenced upload is no longer available: {missing_upload_id
Error message
Referenced upload is no longer available: {missing_upload_id} What it means
ValueError raised when persisting a new chat message: reserve_message_upload_references walks the message content/metadata for upload attachment references and finds an upload id that no longer exists (or is not owned by the session owner). This fails the write closed so transcripts never reference deleted uploads.
Source
Thrown at core/session_manager.py:248
db = SessionLocal()
try:
db_session = db.query(DbSession).filter(DbSession.id == session_id).first()
if db_session is None:
# A stream/tool callback can outlive a session delete. Do not
# create a chat_messages row with no parent session; also drop
# any stale cached session so later writes fail closed too.
self.sessions.pop(session_id, None)
logger.warning("Dropping message for deleted session %s", session_id)
return
missing_upload_id = reserve_message_upload_references(
getattr(self, "upload_handler", None),
getattr(db_session, "owner", None),
message.content,
message.metadata,
)
if missing_upload_id:
raise ValueError(
f"Referenced upload is no longer available: {missing_upload_id}"
)
msg_id = str(uuid.uuid4())
msg_time = datetime.utcnow()
if message.metadata is None:
message.metadata = {}
message.metadata.setdefault('timestamp', _message_timestamp_iso(msg_time))
# Multimodal content may contain provider data URLs for the live
# model call. Persist only readable text plus attachment references
# so chat_messages/FTS do not duplicate upload bytes.
_content = persistable_message_content(message.content, message.metadata)
db_message = DbChatMessage(
id=msg_id,
session_id=session_id,
role=message.role,
content=_content,
meta_data=json.dumps(message.metadata) if message.metadata else None,View on GitHub (pinned to f9235ebbf1)
Solutions
- Re-upload the file and send a new message referencing the fresh upload id
- If cleanup is racing active chats, exclude recently-referenced uploads from retention rules
- Verify the session owner matches the upload owner when sharing contexts across accounts
- On the client, drop stale attachment references before retrying the send
Example fix
# before
session_manager.add_message(session_id, message) # references deleted upload
# after — prune dead references first
alive = [u for u in message.metadata.get('uploads', []) if upload_handler.get(u['id'])]
message.metadata['uploads'] = alive
session_manager.add_message(session_id, message) Defensive patterns
Strategy: validation
Validate before calling
upload_ids = [u.get('id') for u in (message.metadata or {}).get('uploads', [])]
missing = [i for i in upload_ids if not upload_handler.get(i)]
if missing:
raise ClientVisibleError(f'Attachments no longer available: {missing}') Try / catch
try:
sm.add_message(session_id, message)
except ValueError as e:
if 'no longer available' in str(e):
strip_dead_uploads(message)
sm.add_message(session_id, message) # retry without stale refs
else:
raise Prevention
- Check upload ids exist before sending messages that reference them
- Exclude recently-referenced uploads from retention cleanup
- Handle the ValueError client-side by re-uploading, not by retrying unchanged
When it happens
Trigger: Sending/adding a message that references an upload id which was deleted by cleanup or another session, or an upload owned by a different user than db_session.owner. Raised inside add_message/persist before the row is inserted.
Common situations: Long-lived chat tab after uploads were pruned by retention/cleanup; upload deleted from another device; owner mismatch after account or session ownership changes; replaying old client state after server-side purge.
Related errors
- Invalid message attachment metadata
- content is required
- Referenced upload is no longer available: {missing_id}
- No files uploaded
- d && d.detail ? d.detail : ('HTTP ' + res.status)
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/35dddb2d4b54a5d7.
Report an issue: GitHub.