affaan-m/ECC · error · ValueError

must be a nonempty string

Error message

{name} must be a nonempty string

What it means

The _text helper validates that a value is a nonempty, non-whitespace string and is used to validate names and paths across the tasteforge asset pipeline (_path, _assets, _provenance, _bundle, _taste). Any value that is None, a non-string (int, Path passed as name, etc.), or blank raises this ValueError with the given field name in the message.

Solutions

  1. Supply the missing value as a nonempty string.
  2. Check the field name in the message to see which argument is wrong.
  3. Coerce/convert values: str(value) for numbers, str(path) for Path objects.
  4. Validate inputs with a schema or helper before calling the asset API.

Example fix

// before
ingest_assets(sp, name=None, paths=[...])

// after
ingest_assets(sp, name="pack-v1", paths=[...])
Defensive patterns

Strategy: validation

Validate before calling

def require_text(v, name):
    if not isinstance(v, str) or not v.strip():
        raise ValueError(f"{name} must be a nonempty string")
    return v

require_text(name, "name")

Type guard

def is_nonempty_str(v) -> bool:
    return isinstance(v, str) and bool(v.strip())

Try / catch

try:
    assets = ingest_assets(sp, name=name, paths=paths)
except ValueError as e:
    if "must be a nonempty string" in str(e):
        raise UserInputError(f"fix field in '{e}': supply a nonempty string") from e
    raise

Prevention

When it happens

Trigger: Calling ingest_assets/validate_assets/bundle/taste functions with a missing, None, or non-string name/path argument — e.g. name=None, name=123, or name=" ".

Common situations: Config dict missing the key so .get() yields None; passing a pathlib.Path where a name string is expected; blank values from environment variables or CLI flags that default to empty.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/57937e27d94ad800. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/tasteforge/assets.py:25

"""
from __future__ import annotations

import hashlib
import json
import os
import stat
import struct
from pathlib import Path
from typing import Any

SCHEMA = 'tasteforge.assets.v1'
MODALITIES = {'image', 'video', '3d_asset'}
ORIGINS = {'local_passthrough', 'external_result', 'recovered_unverified'}


def _text(value: Any, name: str) -> str:
    if not isinstance(value, str) or not value.strip():
        raise ValueError(f'{name} must be a nonempty string')
    return value


def _path(value: Any, base: Path) -> Path:
    raw = _text(str(value) if isinstance(value, Path) else value, 'path')
    if '://' in raw or raw.startswith(('file:', 'http:', 'https:')):
        raise ValueError('Only local filesystem paths are supported')
    path = Path(raw).expanduser()
    if not path.is_absolute():
        path = base / path
    # Check before resolving '..' to avoid hiding a symlink in the path.
    for part in (path, *path.parents):
        if part.is_symlink():
            raise ValueError(f'Symlinks are not accepted: {part}')
    return path.resolve()


def _fingerprint(path: Path, modality: str | None = None) -> dict[str, Any]:

View on GitHub (pinned to 8321021c54)