zylon-ai/private-gpt · error · ValueError
'oneOf' must be an array of schemas
Error message
'oneOf' must be an array of schemas
What it means
Pydantic field-validator error on SkillFile.path when the value starts with '/'. Absolute paths are rejected to keep skill files inside the skill root; the shared message ('path must be relative and cannot contain ..'') covers the absolute-path case as well. Surfaces as a 422 from FastAPI request validation.
Source
Thrown at private_gpt/chat/schema_models.py:95
sanitized = _handle_dunder_names(sanitized)
sanitized = _handle_python_keywords(sanitized)
sanitized = _handle_reserved_basemodel_attributes(sanitized)
return sanitized
def _validate_json_schema_item(schema: dict[str, Any], strict: bool = True) -> None:
"""Validate that the schema is a valid JSON Schema object."""
if not isinstance(schema, dict):
raise ValueError("Schema must be a dictionary representing JSON Schema")
if schema == {}:
return
# Handle combinators first
if "oneOf" in schema:
if not isinstance(schema["oneOf"], list):
raise ValueError("'oneOf' must be an array of schemas")
for sub_schema in schema["oneOf"]:
_validate_json_schema_item(sub_schema, strict=False)
return # oneOf schemas don't need type field
if "anyOf" in schema:
if not isinstance(schema["anyOf"], list):
raise ValueError("'anyOf' must be an array of schemas")
for sub_schema in schema["anyOf"]:
_validate_json_schema_item(sub_schema, strict=False)
return # anyOf schemas don't need type field
if "allOf" in schema:
if not isinstance(schema["allOf"], list):
raise ValueError("'allOf' must be an array of schemas")
for sub_schema in schema["allOf"]:
_validate_json_schema_item(sub_schema, strict=False)
return # allOf schemas don't need type field
View on GitHub (pinned to 4a030776a3)
Solutions
- Strip the leading slash and any root prefix: send path relative to the skill root (e.g. 'SKILL.md', 'assets/logo.png').
- When zipping/uploading, map each file to its arcname within the bundle.
- Add client-side validation mirroring the server rules before submit.
Example fix
# before
{"path": "/home/me/skills/acme/SKILL.md", "content_base64": "..."}
# after
{"path": "SKILL.md", "content_base64": "..."} Defensive patterns
Strategy: validation
Validate before calling
function toSkillPath(raw) {
if (raw.startsWith('/')) throw new Error('absolute path not allowed');
if (raw.includes('\\')) throw new Error("use '/' separators");
if (raw.split('/').includes('..')) throw new Error('traversal not allowed');
return raw;
} Type guard
const isRelativeSkillPath = (p) =>
typeof p === 'string' && p.length >= 1 && p.length <= 512 &&
!p.startsWith('/') && !p.includes('\\') && !p.split('/').includes('..'); Prevention
- Always send paths relative to the skill root (e.g. 'SKILL.md')
- Use zip arcnames when batch-importing skill bundles
- Mirror the server validator client-side to fail fast with better messages
When it happens
Trigger: POST/PATCH a skill (or version) with a files[] entry whose path is '/SKILL.md' or any leading-slash path; client sending OS-native absolute paths.
Common situations: Frontend passing a file's absolute filesystem path instead of its key within the skill bundle; zip extraction code that preserves leading slashes; scripts ported from an API that allowed absolute paths.
Related errors
- 'anyOf' must be an array of schemas
- 'allOf' must be an array of schemas
- Provide SKILL.md either in files or skill_md
- Invalid system item in list (dict): {item}
- Schema must define a 'type' field
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/8504848a8dc30ee4.
Report an issue: GitHub.