kubernetes/kops · error

ResolveS3Region must be called before building a nodeup scri

Error message

ResolveS3Region must be called before building a nodeup script with an s3:// source

What it means

Build refuses to render the nodeup script when the source uses the s3:// scheme but b.S3Region was never populated. S3 downloads require a region for the bootstrap endpoint, and kops makes the caller (e.g. GetBootstrapData) invoke ResolveS3Region first; this error is the guard against forgetting that step.

Source

Thrown at pkg/model/resources/nodeup.go:319

	// Reject ports, IPv6 hosts, userinfo, queries, and fragments, which the account-based
	// blob.core.windows.net URL cannot represent, so they fail here instead of in the boot retry loop.
	if u.Scheme != "azureblob" || u.Host == "" || u.Hostname() != u.Host || u.User != nil || u.RawQuery != "" || u.Fragment != "" || container == "" || key == "" {
		return "", fmt.Errorf("invalid Azure Blob location; expected azureblob://<account>/<container>/<key>")
	}

	return "azureblob://" + u.Host + httpbinding.EscapePath(u.Path, false), nil
}

func (b *NodeUpScript) Build() (fi.Resource, error) {
	if b.ProxyEnv == nil {
		b.ProxyEnv = funcEmptyString
	}
	if b.EnvironmentVariables == nil {
		b.EnvironmentVariables = funcEmptyString
	}

	if b.useS3Download() && b.S3Region == "" {
		return nil, fmt.Errorf("ResolveS3Region must be called before building a nodeup script with an s3:// source")
	}

	if b.useBlobDownload() {
		// The script hard-codes the public cloud blob.core.windows.net endpoint suffix.
		// Azure environment names are case-insensitive; AzureCloud is the CLI name of the public cloud.
		if azureEnv := os.Getenv("AZURE_ENVIRONMENT"); azureEnv != "" && !strings.EqualFold(azureEnv, "AzurePublicCloud") && !strings.EqualFold(azureEnv, "AzureCloud") {
			return nil, fmt.Errorf("downloading nodeup from an azureblob:// URL is not supported in Azure environment %q", azureEnv)
		}
	}

	functions := template.FuncMap{
		"NodeUpSourceAmd64": func() (string, error) {
			return b.nodeUpSource(architectures.ArchitectureAmd64)
		},
		"NodeUpSourceHashAmd64": func() string {
			if b.NodeUpAssets[architectures.ArchitectureAmd64] != nil {
				return b.NodeUpAssets[architectures.ArchitectureAmd64].Hash.Hex()
			}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Call nodeUpScript.ResolveS3Region(ctx) before Build when using an s3:// source.
  2. If you construct NodeUpScript yourself, replicate the order used in the apply path: build VFS path, resolve region, then Build.
  3. For non-S3 sources this check is skipped — confirm the source really should be s3://.
  4. Update custom tooling/tests to follow the documented sequence.

Example fix

// before
script := &resources.NodeUpScript{NodeUpSource: "s3://bucket/nodeup"}
fi, err := script.Build(arch)
// after
script := &resources.NodeUpScript{NodeUpSource: "s3://bucket/nodeup"}
if err := script.ResolveS3Region(ctx); err != nil { return err }
fi, err := script.Build(arch)
Defensive patterns

Strategy: try-catch

Validate before calling

if b.useS3Download() && b.S3Region == "" {
    if err := b.ResolveS3Region(ctx); err != nil { return err }
}

Type guard

func s3RegionResolved(b *resources.NodeUpScript) bool { return b.S3Region != "" }

Try / catch

if err := script.ResolveS3Region(ctx); err != nil {
    return fmt.Errorf("resolve S3 region before Build: %w", err)
}
fi, err := script.Build(arch)

Prevention

When it happens

Trigger: Calling Build, GetBootstrapData, or kubeEnv on a NodeUpScript whose NodeUpSource contains an s3:// location without first calling ResolveS3Region(ctx) on the same NodeUpScript instance.

Common situations: New integration code or tests constructing resources.NodeUpScript directly and skipping the ResolveS3Region call that the normal kops apply flow performs; refactors that reorder construction and resolution.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/0525f89f736a8563. Report an issue: GitHub.