docker/cli · error

failed to retrieve TLS data

Error message

failed to retrieve TLS data (%s) for context %q: %w

What it means

Returned by LoadTLSData in the per-file loop (tlsdata.go:54) when store.Reader.GetTLSData fails to read one specific TLS file (ca.pem, cert.pem, or key.pem) for an endpoint of a context. The message names the offending file (%s = f) and the context (%q), wrapping the underlying read error.

Solutions

  1. Re-run `docker context update <name> --docker-tls-verify ... --docker-cert-path ...` to rewrite the cert bundle atomically.
  2. Inspect permissions on ca.pem/cert.pem/key.pem under the context's endpoint dir and restore 0600 readable-by-user perms.
  3. If files are genuinely missing, recreate the context with the correct --docker-cert-path / --tls* flags.
  4. Avoid running multiple docker-context-mutating commands in parallel against the same context.

Example fix

// before: assumes all listed TLS files are still readable
tls, err := context.LoadTLSData(s, name, endpoint)

// after: surface the missing file name explicitly and offer to refresh
if err != nil {
    if _, statErr := os.Stat(filepath.Join(dir, "key.pem")); statErr != nil {
        log.Warnf("TLS file vanished for %s; suggest `docker context update`", endpoint)
    }
    return err
}
Defensive patterns

Strategy: try-catch

Try / catch

// Per-file read failures are best handled by catching and refreshing the bundle
tls, err := context.LoadTLSData(s, contextName, endpointName)
if err != nil {
    log.Warnf("TLS load failed (%v); refreshing context %s", err, contextName)
    // trigger a context update that rewrites ca/cert/key atomically
    _ = refreshContext(contextName)
    tls, err = context.LoadTLSData(s, contextName, endpointName)
}
if err != nil { return err }

Prevention

When it happens

Trigger: An endpoint's TLS directory is listed successfully (ca/cert/key files appear) but reading one of those individual files fails — e.g. the file was deleted between the list and the read (race), the file has 0000 perms, or the disk I/O errored. The switch then never assigns it to tlsData because GetTLSData returned an error first.

Common situations: Concurrent docker context update/removal, a half-written file from a killed docker process, files restored from a backup with restrictive permissions, or antivirus/audit tooling locking the key file.

Understand the failure class

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/2b835fd6d3a37269. Report an issue: GitHub.

Appendix: source

Thrown at cli/context/tlsdata.go:55

	}
	if data.Key != nil {
		result.Files[keyKey] = data.Key
	}
	return &result
}

// LoadTLSData loads TLS data from the store
func LoadTLSData(s store.Reader, contextName, endpointName string) (*TLSData, error) {
	tlsFiles, err := s.ListTLSFiles(contextName)
	if err != nil {
		return nil, fmt.Errorf("failed to retrieve TLS files for context %q: %w", contextName, err)
	}
	if epTLSFiles, ok := tlsFiles[endpointName]; ok {
		var tlsData TLSData
		for _, f := range epTLSFiles {
			data, err := s.GetTLSData(contextName, endpointName, f)
			if err != nil {
				return nil, fmt.Errorf("failed to retrieve TLS data (%s) for context %q: %w", f, contextName, err)
			}
			switch f {
			case caKey:
				tlsData.CA = data
			case certKey:
				tlsData.Cert = data
			case keyKey:
				tlsData.Key = data
			default:
				logrus.Warnf("unknown file in context %s TLS bundle: %s", contextName, f)
			}
		}
		return &tlsData, nil
	}
	return nil, nil
}

// TLSDataFromFiles reads files into a TLSData struct (or returns nil if all paths are empty)

View on GitHub (pinned to 4f84911bfe)