github/spec-kit · error · ValueError

providers[{i}]: '{field_name}' must be a non-empty string

Error message

providers[{i}]: '{field_name}' must be a non-empty string

What it means

Follow-up guard for `auth: azure-ad`: after the presence check, each of `tenant_id`, `client_id`, `client_secret_env` is verified to be a non-empty, non-whitespace string. It reports the exact offending field name in the message.

Source

Thrown at src/specify_cli/authentication/config.py:198

                raise ValueError(
                    f"providers[{i}]: auth={auth!r} requires 'token' or 'token_env'"
                )
        elif auth == "azure-ad":
            tenant_id = entry_raw.get("tenant_id")
            client_id = entry_raw.get("client_id")
            client_secret_env = entry_raw.get("client_secret_env")
            if not all([tenant_id, client_id, client_secret_env]):
                raise ValueError(
                    f"providers[{i}]: auth='azure-ad' requires "
                    "'tenant_id', 'client_id', and 'client_secret_env'"
                )
            for field_name, field_val in [
                ("tenant_id", tenant_id),
                ("client_id", client_id),
                ("client_secret_env", client_secret_env),
            ]:
                if not isinstance(field_val, str) or not field_val.strip():
                    raise ValueError(
                        f"providers[{i}]: '{field_name}' must be a non-empty string"
                    )
        # azure-cli needs no extra fields

        entries.append(
            AuthConfigEntry(
                hosts=tuple(hosts),
                provider=provider,
                auth=auth,
                token=token,
                token_env=_norm(token_env),
                tenant_id=_norm(entry_raw.get("tenant_id")),
                client_id=_norm(entry_raw.get("client_id")),
                client_secret_env=_norm(entry_raw.get("client_secret_env")),
            )
        )

    return entries

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Quote the value so YAML parses it as a string: `tenant_id: "12345678-..."`
  2. Check the field named in the error message specifically
  3. Trim accidental whitespace-only values

Example fix

# before
tenant_id: 12345678-1234-1234-1234-123456789012   # may parse oddly or be blank

# after
tenant_id: "12345678-1234-1234-1234-123456789012"
Defensive patterns

Strategy: validation

Validate before calling

for k in ("tenant_id", "client_id", "client_secret_env"):
    v = entry.get(k)
    if v is not None and not (isinstance(v, str) and v.strip()):
        raise SystemExit(f"{k} must be a quoted non-empty string (YAML parses bare digits as int)")

Type guard

def azure_fields_are_strings(entry: dict) -> bool:
    return all(entry.get(k) is None or isinstance(entry.get(k), str)
               for k in ("tenant_id", "client_id", "client_secret_env"))

Try / catch

try:
    load_auth_config(raw)
except ValueError as exc:
    if "must be a non-empty string" in str(exc) and entry.get("auth") == "azure-ad":
        # quote the offending field named in the message and reload
        raise
    raise

Prevention

When it happens

Trigger: One of the three azure-ad fields is a non-string type (e.g. an int tenant/client id from unquoted YAML) or a whitespace-only string; the presence check at :188 only catches falsy values, so `tenant_id: 12345` passes it and fails here.

Common situations: Azure tenant IDs and client (app) IDs are long digit/UUID strings; unquoted numeric IDs parse as ints in YAML and then fail this isinstance check.

Related errors


AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14). Data as JSON: /api/errors/a6d45f7a8dfebca1. Report an issue: GitHub.