NousResearch/hermes-agent · warning · BlueprintFillError

unknown slot{'s' if len(unknown) > 1 else ''}: {', '.join(un

Error message

unknown slot{'s' if len(unknown) > 1 else ''}: {', '.join(unknown)} — valid: {', '.join(s.name for s in blueprint.slots)}

What it means

BlueprintFillError from fill_blueprint: the values dict contains keys that are not slot names defined on the blueprint. Unknown keys are rejected on purpose — the docstring calls out that a typo'd tiem=07:15 must not silently create a job at the default time. The message enumerates the valid slot names.

Source

Thrown at cron/blueprint_catalog.py:764

def fill_blueprint(
    blueprint: AutomationBlueprint,
    values: Dict[str, Any],
    *,
    origin: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
    """Validate ``values`` and return ``cron.jobs.create_job`` kwargs.

    Missing required (non-optional) slots raise BlueprintFillError naming the
    slot, so a form can show field errors and the agent knows what to ask.
    Unknown slot names are rejected (a typo'd ``tiem=07:15`` must not silently
    create a job with the default time). Enum values are checked against their
    options. The result is passed straight to ``create_job`` — no second schema.
    """
    known = {s.name for s in blueprint.slots}
    unknown = sorted(set(values) - known)
    if unknown:
        raise BlueprintFillError(
            f"unknown slot{'s' if len(unknown) > 1 else ''}: "
            f"{', '.join(unknown)} — valid: {', '.join(s.name for s in blueprint.slots)}"
        )
    resolved: Dict[str, Any] = {}
    for s in blueprint.slots:
        raw = values.get(s.name, s.default)
        if raw in (None, ""):
            if s.optional:
                continue
            raise BlueprintFillError(f"missing required value: {s.name} ({s.label})")
        if s.type == "enum" and s.strict and s.options and str(raw) not in {str(o) for o in s.options}:
            raise BlueprintFillError(
                f"{s.name}={raw!r} not allowed — one of {', '.join(map(str, s.options))}"
            )
        resolved[s.name] = raw

    schedule = _resolve_schedule(blueprint, resolved)

View on GitHub (pinned to c896c09c42)

Solutions

  1. Read the valid names listed in the error and re-submit with only those keys
  2. Inspect blueprint.slots ([s.name for s in bp.slots]) before building the values dict
  3. For schedule overrides use the reserved 'schedule' key, not cron field names

Example fix

# before
fill_blueprint(bp, {"tiem": "07:15"})
# BlueprintFillError: unknown slot: tiem — valid: time, day, deliver

# after
fill_blueprint(bp, {"time": "07:15"})
Defensive patterns

Strategy: type-guard

Validate before calling

def only_known_slots(bp, values: dict) -> dict:
    known = {s.name for s in bp.slots} | {"schedule"}
    unknown = set(values) - known
    if unknown:
        raise KeyError(f"typo? {sorted(unknown)}; valid: {sorted(known)}")
    return values

Type guard

from cron.blueprint_catalog import Blueprint

def is_valid_slot_map(bp: Blueprint, values: dict) -> bool:
    known = {s.name for s in bp.slots}
    return set(values) <= known

Try / catch

from cron.blueprint_catalog import BlueprintFillError

try:
    spec = fill_blueprint(bp, values)
except BlueprintFillError as e:
    if str(e).startswith("unknown slot"):
        raise ValueError(f"Fix slot names: {e}") from e
    raise

Prevention

When it happens

Trigger: fill_blueprint(bp, {'tiem': '07:15', 'day': 'monday'}) — 'tiem' is not in {s.name for s in bp.slots}, so it raises before any other validation runs.

Common situations: Typos in slot names; passing schedule-construction keywords (like 'hour'/'minute') directly instead of the slot 'time'; stale caller code after a blueprint renamed its slots.

Related errors


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/4092cc653b9e0608. Report an issue: GitHub.