kubernetes/kops · error
unable to fetch metadata: %w
Error message
unable to fetch metadata: %w
What it means
CreateToken (upup/pkg/fi/cloudup/openstack/openstackmetadata/authenticator.go:39) builds an authentication token from the instance's local metadata (ServerID). If GetLocalMetadata fails — because neither the config drive nor the metadata service could be read — the underlying error is wrapped with this message.
Source
Thrown at upup/pkg/fi/cloudup/openstack/openstackmetadata/authenticator.go:39
"k8s.io/kops/pkg/bootstrap"
)
const OpenstackAuthenticationTokenPrefix = "x-openstack-id " //nolint:gosec // This is an authentication scheme prefix, not a credential.
type openstackAuthenticator struct {
}
var _ bootstrap.Authenticator = (*openstackAuthenticator)(nil)
func NewOpenstackAuthenticator() (bootstrap.Authenticator, error) {
return &openstackAuthenticator{}, nil
}
func (o *openstackAuthenticator) CreateToken(body []byte) (string, error) {
metadata, err := GetLocalMetadata()
if err != nil {
return "", fmt.Errorf("unable to fetch metadata: %w", err)
}
return OpenstackAuthenticationTokenPrefix + metadata.ServerID, nil
}
View on GitHub (pinned to 4c8573c808)
Solutions
- Ensure the instance was booted with a config drive (nova boot --config-drive true or the flavor/image default) or that the metadata service (169.254.169.254) is reachable.
- Inspect the wrapped cause (%w) in the error chain to see whether it came from getFromConfigDrive or getFromMetadataService.
- Verify the metadata search order configured on the instance only contains 'configDrive' and 'metadataService'.
- Check network/security-group rules allow egress to the metadata service endpoint.
Example fix
// before
metadata, err := GetLocalMetadata()
if err != nil {
return "", fmt.Errorf("unable to fetch metadata: %w", err)
}
// after — surface which source failed for faster diagnosis
metadata, err := GetLocalMetadata()
if err != nil {
return "", fmt.Errorf("unable to fetch metadata (check config drive attachment and 169.254.169.254 reachability): %w", err)
} Defensive patterns
Strategy: fallback
Validate before calling
// Check that at least one metadata source is plausibly available
if _, err := os.Stat("/dev/disk/by-label/" + "config-2"); err != nil {
resp, err := http.Get("http://169.254.169.254/openstack/latest/meta_data.json")
if err != nil || resp.StatusCode != http.StatusOK {
return errors.New("neither config drive nor metadata service is reachable")
}
} Try / catch
token, err := authenticator.CreateToken(body)
if err != nil {
var pathErr *fs.PathError
if errors.As(err, &pathErr) {
// config-drive read failed — fall back to metadata-service-only mode
}
return fmt.Errorf("token creation failed, metadata source unavailable: %w", err)
} Prevention
- Boot instances with --config-drive true so local metadata is always present.
- Keep egress to 169.254.169.254 unblocked in instance security groups.
- Unwrap the %w error chain to identify which source (config drive vs metadata service) failed.
- Test metadata availability as a node bootstrap preflight step.
When it happens
Trigger: GetLocalMetadata() returns an error: blkid cannot find a config-drive device, the config drive cannot be mounted/read, the metadata service HTTP request fails or returns non-200, or the configured search order contains invalid options.
Common situations: Node bootstrapping on an OpenStack VM where the config drive was not attached at instance creation; the nova metadata service is unreachable from the instance network; the instance was created without config_drive enabled while metadata service is firewalled.
Related errors
- failed to get info for server %q: %w
- failed to retrieve server ID: %w
- error building openstack authenticated client: %v
- error getting cloud instance group %q: %v
- unable to run blkid: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/c7b68853f98531f4.
Report an issue: GitHub.