zylon-ai/private-gpt · error · SkillDomainError

MIME_TYPE_UNKNOWN

MIME_TYPE_UNKNOWN

Error message

Could not determine MIME type for file: {value.path}

What it means

SkillDomainError with code MIME_TYPE_UNKNOWN: after resolving uploaded files, any file whose mime_type is still falsy raises this. mime_type is set from the '.md' shortcut, mimetypes.guess_type, or the default_mime_type parameter — so it only fires when default_mime_type was explicitly passed as None and the extension is unrecognized.

Source

Thrown at private_gpt/server/skills/skills_files.py:92

            resolved = {
                "SKILL.md": StoredFile(
                    path="SKILL.md",
                    content=stored.content,
                    mime_type="text/markdown",
                )
            }

    for value in resolved.values():
        if not value.mime_type:
            mime_type, _ = (
                ("text/markdown", None)
                if value.path.endswith(".md")
                else mimetypes.guess_type(value.path)
            )
            value.mime_type = mime_type or default_mime_type

        if not value.mime_type:
            raise SkillDomainError(
                SkillErrorCode.MIME_TYPE_UNKNOWN,
                f"Could not determine MIME type for file: {value.path}",
            )

    if "SKILL.md" not in resolved:
        raise SkillDomainError(
            SkillErrorCode.MISSING_SKILL_MD, "Upload must include a SKILL.md file."
        )

    return list(resolved.values())


def _normalize_path(path: str) -> str:
    # Normalize backslashes to forward slashes
    path = path.replace("\\", "/")

    parsed = PurePosixPath(path)

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Pass default_mime_type='application/octet-stream' (the documented default) so unknown extensions fall back instead of erroring.
  2. Rename the offending file to a known extension before upload.
  3. Register the custom extension with mimetypes (mimetypes.add_type) if it is a format your deployment genuinely supports.
  4. Inspect the resolved file list to find which path has no mime_type and fix that entry.

Example fix

# before
files = await stored_files_from_uploads(uploads, default_mime_type=None)
# after
files = await stored_files_from_uploads(uploads)  # default fallback 'application/octet-stream'
Defensive patterns

Strategy: validation

Validate before calling

import mimetypes
KNOWN = {'.md', '.txt', '.py', '.json', '.pdf', '.png', '.yaml'}
unknown = [p for p in paths if mimetypes.guess_type(p)[0] is None and not p.endswith('.md') and Path(p).suffix not in KNOWN]
assert not unknown, f'unrecognized extensions: {unknown}'

Type guard

const hasKnownExtension = (path: string): boolean =>
  /\.(md|txt|py|json|pdf|png|ya?ml)$/i.test(path);

Try / catch

try:
    files = await stored_files_from_uploads(uploads, default_mime_type=None)
except SkillDomainError as e:
    if e.code == SkillErrorCode.MIME_TYPE_UNKNOWN:
        files = await stored_files_from_uploads(uploads)  # retry with octet-stream fallback
    else:
        raise

Prevention

When it happens

Trigger: Calling stored_files_from_uploads(uploads, default_mime_type=None) (or None default propagation) with a file whose path has an extension mimetypes cannot map (e.g. '.tmp', '.dat', no extension) — note this specific error can only trigger when the caller disabled the octet-stream fallback.

Common situations: Callers passing None to enforce strict mime detection on user uploads; extension-less files extracted from zips; exotic or custom extensions not in the system mime table; differing mimetypes registries across OS images making CI behave differently than dev.

Related errors


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