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 entriesView on GitHub (pinned to bf88c9f9a8)
Solutions
- Quote the value so YAML parses it as a string: `tenant_id: "12345678-..."`
- Check the field named in the error message specifically
- 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
- Quote all Azure IDs in YAML — UUID/numeric-looking values parse as non-strings otherwise
- Use str() coercion when generating the config programmatically
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
- providers[{i}]: auth='azure-ad' requires 'tenant_id', 'clien
- providers[{i}]: invalid host pattern {h!r}. Only exact hostn
- providers[{i}]: 'provider' must be a non-empty string
- providers[{i}]: 'auth' must be a non-empty string
- providers[{i}]: 'token' must be a non-empty string
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/a6d45f7a8dfebca1.
Report an issue: GitHub.