jdx/mise · error

`auth` for is not `user:password

Error message

`auth` for {key} is not `user:password`

What it means

When reading Docker-style registry credentials (e.g. `~/.docker/config.json`), the `auth` field must be base64 of `username:password`. `credential_from_entry` decodes it and splits on the first `:`; if no colon exists, it bails because the credential cannot be split into username/secret.

Solutions

  1. Set `auth` to base64 of `username:password` (`echo -n 'user:pass' | base64`) in the registry config entry
  2. Use `docker login` (or the registry CLI) to regenerate the credential entry correctly
  3. If using an identity token flow, put the token in the `identitytoken` field instead of `auth`
  4. Remove the malformed entry and re-authenticate against the registry

Example fix

# before (config.json)
"auth": "c2VjcmV0"  // base64 of just the password
# after
"auth": "dXNlcjpzZWNyZXQ="  // base64 of "user:secret"
Defensive patterns

Strategy: validation

Validate before calling

use base64::Engine;
fn auth_is_user_password(auth: &str) -> bool {
    base64::engine::general_purpose::STANDARD
        .decode(auth.trim()).ok()
        .and_then(|b| String::from_utf8(b).ok())
        .is_some_and(|s| s.contains(':'))
}

Try / catch

match result {
    Err(e) if e.to_string().contains("is not `user:password`") => {
        // re-run `docker login` to regenerate the auth entry, then retry
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling OCI-authenticated operations with a docker config entry whose `auth` field decodes to a string without a `:` — e.g. `auth` was set to a raw token, only a username, or base64 of a password without the username prefix.

Common situations: Users pasting an access token directly into `auth`; manually crafting config.json entries; credential created by tooling that only stores the password; corrupted or truncated auth values.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/f2f803af38068eff. Report an issue: GitHub.

Appendix: source

Thrown at src/oci/auth.rs:177

            Err(e) => {
                debug!("credsStore helper {helper} has no credentials for {registry}: {e}");
            }
        }
    }

    Ok(None)
}

fn credential_from_entry(entry: &AuthEntry, key: &str) -> Result<Option<Credential>> {
    let (mut username, mut secret) = (entry.username.clone(), entry.password.clone());
    if let Some(auth) = entry.auth.as_deref().filter(|a| !a.is_empty()) {
        let decoded = BASE64_STANDARD
            .decode(auth.trim())
            .wrap_err_with(|| format!("decoding base64 `auth` for {key}"))?;
        let decoded = String::from_utf8(decoded)
            .wrap_err_with(|| format!("`auth` for {key} is not valid UTF-8"))?;
        let Some((u, p)) = decoded.split_once(':') else {
            bail!("`auth` for {key} is not `user:password`");
        };
        username = Some(u.to_string());
        secret = Some(p.to_string());
    }
    // An identity token (docker.io "Docker Desktop" login flow) replaces the
    // password; the username from `auth` is ignored by registries in this
    // mode but `<token>` is the conventional placeholder.
    if let Some(token) = entry.identity_token.as_deref().filter(|t| !t.is_empty()) {
        return Ok(Some(Credential {
            username: "<token>".to_string(),
            secret: token.to_string(),
        }));
    }
    match (username, secret) {
        (Some(u), Some(p)) => Ok(Some(Credential {
            username: u,
            secret: p,
        })),

View on GitHub (pinned to 533346cc37)