{"record":{"id":"f2f803af38068eff","repo":"jdx/mise","slug":"auth-for-key-is-not-user-password","errorCode":null,"errorMessage":"`auth` for {key} is not `user:password`","messagePattern":"`auth` for (.+?) is not `user:password`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/oci/auth.rs","lineNumber":177,"sourceCode":"            Err(e) => {\n                debug!(\"credsStore helper {helper} has no credentials for {registry}: {e}\");\n            }\n        }\n    }\n\n    Ok(None)\n}\n\nfn credential_from_entry(entry: &AuthEntry, key: &str) -> Result<Option<Credential>> {\n    let (mut username, mut secret) = (entry.username.clone(), entry.password.clone());\n    if let Some(auth) = entry.auth.as_deref().filter(|a| !a.is_empty()) {\n        let decoded = BASE64_STANDARD\n            .decode(auth.trim())\n            .wrap_err_with(|| format!(\"decoding base64 `auth` for {key}\"))?;\n        let decoded = String::from_utf8(decoded)\n            .wrap_err_with(|| format!(\"`auth` for {key} is not valid UTF-8\"))?;\n        let Some((u, p)) = decoded.split_once(':') else {\n            bail!(\"`auth` for {key} is not `user:password`\");\n        };\n        username = Some(u.to_string());\n        secret = Some(p.to_string());\n    }\n    // An identity token (docker.io \"Docker Desktop\" login flow) replaces the\n    // password; the username from `auth` is ignored by registries in this\n    // mode but `<token>` is the conventional placeholder.\n    if let Some(token) = entry.identity_token.as_deref().filter(|t| !t.is_empty()) {\n        return Ok(Some(Credential {\n            username: \"<token>\".to_string(),\n            secret: token.to_string(),\n        }));\n    }\n    match (username, secret) {\n        (Some(u), Some(p)) => Ok(Some(Credential {\n            username: u,\n            secret: p,\n        })),","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/oci/auth.rs#L159-L195","documentation":"When mise reads Docker-style credentials (for `mise oci push`/registry auth) from ~/.docker/config.json, an entry's `auth` field must be base64 of `user:password`. After successful base64 decode and UTF-8 validation, the value must contain a colon; a decoded string without one (e.g. a bare API token) violates the format and fails here. Note that a valid `identitytoken` field takes precedence and bypasses this path.","triggerScenarios":"A config.json `auth` value that base64-decodes to a token or username with no ':' separator — commonly written by third-party CLIs, cloud helpers, or manual base64 encoding of registry tokens. Hit during any OCI registry authentication when mise parses the auth entry for that server key.","commonSituations":"Registries whose CLI stores `echo -n <token> | base64` instead of `echo -n user:token | base64`; hand-crafted config.json entries; GitLab/GHCR deploy tokens pasted incorrectly.","solutions":["Re-run `docker login <server>` so a spec-conformant user:password auth entry is written","Replace the `auth` field with explicit `\"username\"` and `\"password\"` fields in config.json","If the secret is a registry identity token, put it in `\"identitytoken\"` (mise maps it to username `<token>`) instead of `auth`","Delete the malformed entry so mise falls back to other credential sources"],"exampleFix":"# before (~/.docker/config.json)\n{\n  \"auths\": {\n    \"ghcr.io\": { \"auth\": \"Z2hwX3Rva2VuMTIzNDU2Nzg5\" }\n  }\n}\n\n# after\n{\n  \"auths\": {\n    \"ghcr.io\": {\n      \"username\": \"myuser\",\n      \"password\": \"ghp_token123456789\"\n    }\n  }\n}","handlingStrategy":"validation","validationCode":"python3 - <<'EOF'\nimport json, base64, sys\ncfg = json.load(open('$HOME/.docker/config.json'))\nfor key, entry in {**cfg.get('auths', {})}.items():\n    auth = entry.get('auth')\n    if auth:\n        try: decoded = base64.b64decode(auth).decode('utf-8')\n        except Exception as e: sys.exit(f'{key}: auth not base64/UTF-8: {e}')\n        if ':' not in decoded: sys.exit(f'{key}: auth decodes without user:password colon')\nprint('docker auth entries OK')\nEOF","typeGuard":"fn auth_is_user_password(auth_b64: &str) -> bool {\n    base64::engine::general_purpose::STANDARD\n        .decode(auth_b64.trim()).ok()\n        .and_then(|b| String::from_utf8(b).ok())\n        .map(|s| s.split_once(':').is_some())\n        .unwrap_or(false)\n}","tryCatchPattern":"Catch this per-server before OCI push; on trigger, skip the entry (fall back to anonymous or explicit username/password) and log which registry key needs re-login, rather than aborting the whole push.","preventionTips":["Create credentials with `docker login` instead of hand-encoding base64","Use `username`/`password` fields or `identitytoken` rather than `auth` for tokens","Validate config.json entries with the decode-and-split check after any manual edit"],"tags":["oci","docker-config","auth","registry","credentials"],"backgroundTag":"docker-registry-auth-malformed","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}