zylon-ai/private-gpt · error · ValueError
Invalid system value: {value}
Error message
Invalid system value: {value} What it means
Raised by GET /skills/{skill_id}/versions/{version} when the skill exists but SkillService.get_version() returns None — i.e. the version token does not resolve to a stored version of that skill. Distinct from the skill-level 404 in the same handler: here the parent exists but the version is gone or unknown.
Source
Thrown at private_gpt/chat/input_models.py:1264
return [System.model_validate(value)]
if isinstance(value, list):
systems: list[System] = []
for item in value:
if isinstance(item, System):
systems.append(item)
elif isinstance(item, TextBlock):
systems.append(System(text=item.text))
elif isinstance(item, str):
systems.append(System(text=item))
elif isinstance(item, dict):
if item.get("type") == "text" and isinstance(item.get("text"), str):
systems.append(System(text=item["text"]))
else:
systems.append(System.model_validate(item))
else:
raise ValueError(f"Invalid system item: {item}")
return systems or [System()]
raise ValueError(f"Invalid system value: {value}")
@field_validator("model", mode="before")
@classmethod
def normalize_model(cls, value: str | None) -> str:
if value is None:
return "default"
return value
@model_validator(mode="after")
def extract_system_messages(self) -> "MessagesInputBase":
"""Extract role=system messages and append them to the system list."""
system_msgs = [msg for msg in self.messages if msg.role == "system"]
if not system_msgs:
return self
self.messages = [msg for msg in self.messages if msg.role != "system"]
for msg in system_msgs:View on GitHub (pinned to 4a030776a3)
Solutions
- Re-list versions for the skill to get current tokens and pick the latest.
- Handle 404 on version fetch gracefully by refreshing the version list.
- Don't persist version tokens long-term; treat them as ephemeral cursors.
Example fix
// before
const v = await skillsApi.getVersion(id, token, col);
// after
let v;
try { v = await skillsApi.getVersion(id, token, col); }
catch (e) {
if (e.status !== 404) throw e;
const list = await skillsApi.listVersions(id, col);
v = list.data[0] ?? null; // fall back to newest version
} Defensive patterns
Strategy: fallback
Validate before calling
const versions = await skillsApi.listVersions(id, collection); if (!versions.data.some((v) => v.version === token)) token = versions.data[0]?.version;
Try / catch
try { return await skillsApi.getVersion(id, token, collection); }
catch (e) {
if (e.status === 404) { const l = await skillsApi.listVersions(id, collection); return l.data[0] ?? null; }
throw e;
} Prevention
- Treat version tokens as ephemeral cursors, not durable references
- Refresh the version list after any delete/version churn
- Distinguish 'skill gone' vs 'version gone' by re-checking the skill
When it happens
Trigger: Using an expired/pruned version token; version deleted by another client; token copied from a different skill or environment.
Common situations: Version-retention policies pruning old versions while clients hold stale tokens; race between viewing and deleting a version.
Related errors
- Unknown message role {self.role}. Expected 'system', 'user',
- Audio size {audio_size} exceeds maximum allowed size of {set
- Invalid tool specification: {tool}
- Invalid system item: {item}
- Schema must be a dictionary representing JSON Schema
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/a138f8e03948eb63.
Report an issue: GitHub.