zylon-ai/private-gpt · error · ValueError

Invalid tool specification: {tool}

Error message

Invalid tool specification: {tool}

What it means

Raised by GET /skills/{skill_id}/versions when the skill itself does not exist in the collection. Versions are only addressable under an existing skill, so the skill-level pre-check fails with 404 before pagination of versions begins.

Source

Thrown at private_gpt/chat/input_models.py:1153

            tool_context = tool.get("context")
            if not isinstance(tool_context, list):
                tool_context = None
        # Try to get the custom name
        name: str = ""
        if isinstance(tool, dict) and tool.get("name"):
            name = tool.get("name") or ""

        return ToolSpecBody(
            name=name or internal_tool_name,
            type=tool_type,
            context=tool_context,
        )
    else:
        # Tools provided (and executed) by the caller
        try:
            return ToolSpecBody.model_validate(tool)
        except Exception as e:
            raise ValueError(f"Invalid tool specification: {tool}") from e


ToolSpecOrString = Annotated[ToolSpecBody, BeforeValidator(validate_tool_spec)]


class CompletionMetadata(BaseModel):
    user_id: str | None = Field(
        default=None,
        description="Opaque user identifier for request attribution.",
        max_length=512,
    )

    model_config = ConfigDict(extra="allow")


class MessagesInputBase(BaseModel):
    """Shared Anthropic-compatible input shape for message-based endpoints."""

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Validate the skill exists (GET /skills/{id}) before navigating to its versions screen.
  2. Clear deep links/caches when a skill 404s and route back to the skill list.
  3. Confirm the collection query parameter matches.

Example fix

// before
router.push(`/skills/${id}/versions`);

// after
const ok = await skillsApi.exists(id, collection);
router.push(ok ? `/skills/${id}/versions` : '/skills');
Defensive patterns

Strategy: validation

Validate before calling

const skill = await skillsApi.get(id, collection).catch(() => null);
if (!skill) redirect('/skills'); // don't even fetch versions

Try / catch

try { return await skillsApi.listVersions(id, collection, { limit, page }); }
catch (e) { if (e.status === 404) return { data: [], hasMore: false }; throw e; }

Prevention

When it happens

Trigger: Listing versions for a deleted skill, an id from a different collection, or a malformed id; navigating to a versions screen from a stale link.

Common situations: Deep links to version history of removed skills; collection context switching in the UI; bookmarks surviving a skill purge.

Related errors


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