testcontainers/testcontainers-java · warning

Docker auth config credsStore field will be ignored…

Error message

Docker auth config credsStore field will be ignored, because value is blank

What it means

RegistryAuthLocator reads the Docker config.json to resolve credentials. If the credsStore field exists but is an empty/blank string, it cannot invoke a credential helper, so it warns that the field is ignored and returns null (falling back to other auth resolution).

Solutions

  1. Fix ~/.docker/config.json: remove the empty credsStore key or set it to a real helper (e.g. "desktop")
  2. Re-run `docker login` so Docker rewrites a valid config.json
  3. Provide credentials another way (explicit AuthConfig, registry mirror without auth)

Example fix

// before (~/.docker/config.json)
{ "auths": {}, "credsStore": "" }
// after
{ "auths": {}, "credsStore": "desktop" }
Defensive patterns

Strategy: validation

Validate before calling

var cfg = new com.fasterxml.jackson.databind.ObjectMapper()
    .readTree(Paths.get(System.getProperty("user.home"), ".docker", "config.json").toFile());
var cs = cfg.path("credsStore");
if (cs.isTextual() && cs.asText().isBlank()) {
    throw new IllegalStateException("config.json has blank credsStore — run docker login");
}

Prevention

When it happens

Trigger: authConfigUsingStore() finds config.get("credsStore") is textual but StringUtils.isBlank when resolving auth for a repository during image pull/push.

Common situations: Corrupted or hand-edited ~/.docker/config.json where credsStore was cleared but left as ""; some tooling writes an empty credsStore key; Docker Desktop upgrades leaving stale fields.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12). Data as JSON: /api/errors/ebb9b1f49a74cfaa. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/testcontainers/utility/RegistryAuthLocator.java:249

    private AuthConfig authConfigUsingHelper(final JsonNode config, final String reposName) throws Exception {
        final JsonNode credHelpers = config.get("credHelpers");
        if (credHelpers != null && credHelpers.size() > 0) {
            final JsonNode helperNode = credHelpers.get(reposName);
            if (helperNode != null && helperNode.isTextual()) {
                final String helper = helperNode.asText();
                return runCredentialProvider(reposName, helper);
            }
        }
        return null;
    }

    private AuthConfig authConfigUsingStore(final JsonNode config, final String reposName) throws Exception {
        final JsonNode credsStoreNode = config.get("credsStore");
        if (credsStoreNode != null && !credsStoreNode.isMissingNode() && credsStoreNode.isTextual()) {
            final String credsStore = credsStoreNode.asText();
            if (StringUtils.isBlank(credsStore)) {
                log.warn("Docker auth config credsStore field will be ignored, because value is blank");
                return null;
            }
            return runCredentialProvider(reposName, credsStore);
        }
        return null;
    }

    private Map.Entry<String, JsonNode> findAuthNode(final JsonNode config, final String reposName) {
        final JsonNode auths = config.get("auths");
        if (auths != null && auths.size() > 0) {
            final Iterator<Map.Entry<String, JsonNode>> fields = auths.fields();
            while (fields.hasNext()) {
                final Map.Entry<String, JsonNode> entry = fields.next();
                if (entry.getKey().endsWith("://" + reposName) || entry.getKey().equals(reposName)) {
                    return entry;
                }
            }
        }

View on GitHub (pinned to 8e549514e3)