fishaudio/fish-speech · error · HTTPException

Invalid token

Error message

Invalid token

What it means

The API server's bearer-token check compares the presented token against --api-key; on mismatch FastAPI returns 401 with detail 'Invalid token'. The check is only active when the server was started with an api_key.

Source

Thrown at tools/api_server.py:42

pyrootutils.setup_root(__file__, indicator=".project-root", pythonpath=True)

from tools.server.api_utils import MsgPackRequest, parse_args
from tools.server.exception_handler import ExceptionHandler
from tools.server.model_manager import ModelManager
from tools.server.views import routes

ENV_ARGS_KEY = "FISH_API_SERVER_ARGS"


class API(ExceptionHandler):
    def __init__(self, args: Namespace | None = None):
        self.args = args or parse_args()

        def api_auth(endpoint):
            async def verify(token: Annotated[str, Depends(bearer_auth)]):
                if token != self.args.api_key:
                    raise HTTPException(401, None, "Invalid token")
                return await endpoint()

            async def passthrough():
                return await endpoint()

            if self.args.api_key is not None:
                return verify
            else:
                return passthrough

        self.routes = Routes(
            routes,  # keep existing routes
            http_middlewares=[api_auth],  # apply api_auth middleware
        )

        # OpenAPIの設定
        self.openapi = OpenAPI(
            Info(

View on GitHub (pinned to befe400174)

Solutions

  1. Send header `Authorization: Bearer <same value as server --api-key>`
  2. Restart the server without --api_key if auth is not needed (dev only)
  3. Check for trailing whitespace/newlines when the key comes from an env var

Example fix

# before
client.set_api_key("wrong-key")
# after
client.set_api_key(os.environ["FISH_API_KEY"])  # same value as server --api-key
Defensive patterns

Strategy: validation

Validate before calling

import os
assert args.api_key is None or os.environ.get("API_KEY") == args.api_key

Try / catch

try:
    client.tts(...)
except HTTPError as e:
    if e.response.status_code == 401:
        refresh_api_key()

Prevention

When it happens

Trigger: Calling any protected endpoint without an Authorization header or with a token different from the server's --api-key.

Common situations: Default client token vs custom server key; stale token after server restart with a new key; missing 'Bearer ' prefix in the header.

Understand the failure class

Related errors


AI-assisted analysis of fishaudio/fish-speech@befe400174 (2026-08-27). Data as JSON: /api/errors/cbce780e19ecec37. Report an issue: GitHub.