zylon-ai/private-gpt · error · ValueError

Invalid system item

Error message

Invalid system item: {item}

What it means

Raised by GET /skills/{skill_id}/versions/{version} when the skill does not exist in the collection (first guard). The route verifies the parent skill before looking up the specific version token.

Solutions

  1. Confirm the skill exists first and handle 404 by falling back to the skill list.
  2. Re-fetch the version list for the skill to obtain valid tokens.
  3. Ensure the collection parameter matches the environment the token came from.

Example fix

// before
const v = await skillsApi.getVersion(id, version, col);

// after
const v = await skillsApi.getVersion(id, version, col).catch((e) => {
  if (e.status === 404) return skillsApi.listVersions(id, col).then(() => null);
  throw e;
});
Defensive patterns

Strategy: try-catch

Validate before calling

const skill = await skillsApi.get(id, collection).catch(() => null);
if (!skill) throw new SkillGoneError(id);

Try / catch

try { return await skillsApi.getVersion(id, version, 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: Fetching a version by token for a skill id that is deleted, in another collection, or invalid.

Common situations: Version-permalink clicked after the skill was removed; cached version tokens reused across environments.

Related errors


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

Appendix: source

Thrown at private_gpt/chat/input_models.py:1262

            if value.get("type") == "text" and isinstance(value.get("text"), str):
                return [System(text=value["text"])]
            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"]

View on GitHub (pinned to 4a030776a3)