PrefectHQ/fastmcp · error · ValueError

The API key is empty

Error message

The API key is empty

What it means

The AuthState pydantic model validates its api_key field with require_nonempty_api_key; a SecretStr whose value is empty or whitespace-only raises ValueError('The API key is empty'). This guards against persisting unusable credentials.

Source

Thrown at fastmcp_slim/fastmcp/cli/deploy/credentials.py:47

CredentialSource = Literal["environment", "stored", "interactive"]


class AuthenticationRequiredError(RuntimeError):
    """No Horizon credential is available without interactive authorization."""


class AuthState(BaseModel):
    model_config = ConfigDict(extra="forbid", frozen=True, populate_by_name=True)

    schema_version: Literal[1] = Field(alias="schemaVersion")
    api_key: SecretStr = Field(alias="apiKey")

    @field_validator("api_key")
    @classmethod
    def require_nonempty_api_key(cls, value: SecretStr) -> SecretStr:
        if not value.get_secret_value().strip():
            raise ValueError("The API key is empty")
        return value


@dataclass(frozen=True)
class ResolvedCredential:
    api_key: SecretStr
    source: CredentialSource


class CredentialStore:
    """Persist the active personal Horizon API key."""

    def __init__(self, state_directory: Path | None = None) -> None:
        if state_directory is None:
            import fastmcp

            state_directory = fastmcp.settings.home / "cli"
        self.path = state_directory / "auth.json"

View on GitHub (pinned to 1f02114297)

Solutions

  1. Supply the actual Horizon API key when saving credentials
  2. Trim accidental whitespace and re-run the login/save step
  3. Re-authenticate with `fastmcp deploy login` if you don't have a valid key
  4. Check the env var or secret source that produced the empty value

Example fix

// before
store.save("")  # The API key is empty
// after
store.save(os.environ["HORIZON_API_KEY"].strip())
Defensive patterns

Strategy: validation

Validate before calling

def has_api_key(value: str | None) -> bool:
    return bool(value and value.strip())

Type guard

def is_nonempty_secret(value: SecretStr | None) -> bool:
    return value is not None and bool(value.get_secret_value().strip())

Try / catch

try:
    AuthState(schemaVersion=1, apiKey=key)
except ValidationError as e:
    print(f"Refusing to save credentials: {e}")

Prevention

When it happens

Trigger: Constructing AuthState with apiKey='' or apiKey=' ', or saving such a value through CredentialStore.save, which catches ValidationError and re-raises as StateFileError.

Common situations: An environment variable or paste operation supplying an empty key; a truncated copy/paste; a CI secret accidentally unset but not rejected earlier.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/802e3435af7749de. Report an issue: GitHub.