affaan-m/ECC · error · FalError

no tier ' ' for slot ' '; have

Error message

no tier '{tier}' for slot '{slot}'; have {sorted(table) if table else 'no tiers'}

What it means

use_tier() raises FalError when the requested (slot, tier) pair does not exist in the TIERS registry — either the slot name is unknown (TIERS.get(slot) is None) or the tier name is not a key in that slot's table. The message helpfully lists the available tier names for the given slot. This guards endpoint repointing against typos and stale tier names.

Solutions

  1. Read the available tiers from the error message and use one of those exact names
  2. Check TIERS (or the module's documented slot/tier table) for the correct slot name first
  3. Print sorted(TIERS) to enumerate valid slots before calling use_tier
  4. Update code after library upgrades where tier names may have been renamed

Example fix

// before
use_tier("image", "quality")  # tier 'quality' doesn't exist
// after
from taste import falapi
print(sorted(falapi.TIERS["image"]))  # e.g. ['fast', 'pro']
falapi.use_tier("image", "pro")
Defensive patterns

Strategy: validation

Validate before calling

from taste import falapi

def safe_use_tier(slot, tier):
    if slot not in falapi.TIERS:
        raise ValueError(f"unknown slot '{slot}'; have {sorted(falapi.TIERS)}")
    if tier not in falapi.TIERS[slot]:
        raise ValueError(f"slot '{slot}' has tiers {sorted(falapi.TIERS[slot])}")
    return falapi.use_tier(slot, tier)

Type guard

def tier_exists(slot: str, tier: str) -> bool:
    table = falapi.TIERS.get(slot)
    return bool(table) and tier in table

Try / catch

try:
    falapi.use_tier(slot, tier)
except falapi.FalError as e:
    print(e)  # message lists valid tiers for the slot
    raise

Prevention

When it happens

Trigger: Calling use_tier('video', 'pro') when slot 'video' doesn't exist in TIERS, or when the tier string is misspelled/renamed, or when checking a tier against the wrong slot.

Common situations: Typos in slot or tier names; using tier names from an older version of the library after a rename; assuming tiers are shared across slots when each slot defines its own set; copying a use_tier call from code targeting a different slot.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at skills/taste-application/scripts/taste/falapi.py:117

    },
    "text_to_3d": {
        "best": "fal-ai/hunyuan-3d/v3.1/pro/text-to-3d",
        "fast": "fal-ai/hunyuan-3d/v3.1/rapid/text-to-3d",
        "value": "tripo3d/h3.1/text-to-3d",
    },
    "text_to_image": {
        "best": "fal-ai/nano-banana-pro",       # $0.15 flat, strongest identity
        "value": "fal-ai/flux-2-pro",           # $0.03 first MP
        "instruct": "openai/gpt-image-2",       # best typography / instructions
    },
}


def use_tier(slot: str, tier: str) -> str:
    """Repoint one slot at a named tier. Returns the endpoint now in use."""
    table = TIERS.get(slot)
    if not table or tier not in table:
        raise FalError(
            f"no tier '{tier}' for slot '{slot}'; "
            f"have {sorted(table) if table else 'no tiers'}"
        )
    ENDPOINTS[slot] = table[tier]
    return ENDPOINTS[slot]


# fal has NO endpoint that renders a mesh to images or video. The catalogue
# splits 3D into image-to-3d, text-to-3d and 3d-to-3d, and every member of
# 3d-to-3d emits another mesh - there is no 3d-to-image or 3d-to-video
# category at all. So a minted GLB cannot re-enter the video graph on fal.
#
# It can re-enter locally: render a turntable here (taste/render3d.py), then
# either assemble the frames with local ffmpeg or push them through
# ``images_to_video`` above. That is why the 3D branch is not a dead end even
# though the platform has no renderer.
NO_RENDER_ENDPOINT = True

View on GitHub (pinned to 8321021c54)