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

  1. Re-list versions for the skill to get current tokens and pick the latest.
  2. Handle 404 on version fetch gracefully by refreshing the version list.
  3. 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

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


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/a138f8e03948eb63. Report an issue: GitHub.