nexu-io/open-design · error · SystemExit

pet id must contain at least one letter or digit

Error message

pet id must contain at least one letter or digit

What it means

Raised by prepare_pet_run.py main() when args.pet_id slugifies to empty after combining --pet-id, --pet-name, and --display-name. slugify discards every character that is not [a-z0-9], so if all three names consist only of symbols/whitespace/emojis, no usable id remains and the run dir cannot be named.

Source

Thrown at skills/hatch-pet/scripts/prepare_pet_run.py:574

    parser.add_argument(
        "--chroma-key",
        default="auto",
        help="Chroma key as #RRGGBB, or auto to choose a safe key from reference colors.",
    )
    parser.add_argument("--force", action="store_true")
    args = parser.parse_args()

    raw_reference_paths = [
        Path(raw_path).expanduser().resolve() for raw_path in args.reference
    ]

    args.display_name = infer_name(args, raw_reference_paths)
    args.pet_name = (args.pet_name or args.display_name).strip()
    args.description = infer_description(args, raw_reference_paths)
    args.pet_notes = infer_pet_notes(args, raw_reference_paths)
    args.pet_id = slugify(args.pet_id or args.pet_name or args.display_name)
    if not args.pet_id:
        raise SystemExit("pet id must contain at least one letter or digit")

    run_dir = (
        Path(args.output_dir).expanduser().resolve()
        if args.output_dir
        else default_output_dir(args.pet_id).resolve()
    )
    if run_dir.exists() and any(run_dir.iterdir()) and not args.force:
        raise SystemExit(
            f"{run_dir} already exists and is not empty; pass --force to reuse it"
        )
    run_dir.mkdir(parents=True, exist_ok=True)

    ref_dir = run_dir / "references"
    prompt_dir = run_dir / "prompts"
    row_prompt_dir = prompt_dir / "rows"
    for directory in [
        ref_dir,
        prompt_dir,

View on GitHub (pinned to 5be4028344)

Solutions

  1. Give the pet a name containing at least one ASCII letter or digit via --pet-id, --pet-name, or --display-name.
  2. If using a reference image, ensure its filename has alphanumerics so infer_name can derive a fallback.
  3. Avoid purely symbolic or emoji-only identifiers.
  4. Re-run prepare_pet_run.py.

Example fix

// before
python prepare_pet_run.py --pet-name "★" --reference cat.png
# SystemExit: pet id must contain at least one letter or digit

// after
python prepare_pet_run.py --pet-name "Star" --reference cat.png
Defensive patterns

Strategy: validation

Validate before calling

import re

def slugify(value: str) -> str:
    value = value.strip().lower()
    value = re.sub(r"[^a-z0-9]+", "-", value)
    value = re.sub(r"-{2,}", "-", value)
    return value.strip("-")

pet_id = slugify(args.pet_id or args.pet_name or args.display_name)
if not pet_id:
    raise SystemExit("pet id must contain at least one letter or digit")

Type guard

def slug_is_valid(value: str) -> bool:
    import re
    s = re.sub(r"[^a-z0-9]+", "-", value.strip().lower()).strip("-")
    return bool(s)

Prevention

When it happens

Trigger: Passing --pet-name "★★★" and no --pet-id; passing --pet-id "---" and no usable name; all of --pet-id/--pet-name/--display-name empty or symbolic and no reference image filename that supplies a fallback name.

Common situations: Emoji-only or symbol-only pet names; empty shell variables expanded into all three flags; names in scripts whose only alphanumerics were stripped by slugify.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/11b0f2245d6a5aa1. Report an issue: GitHub.