kubernetes/kops · error

error closing target: %w

Error message

error closing target: %w

What it means

After tasks succeed, Run() calls target.Finish(taskMap) to finalize. For LocalTarget this flushes any pending operations/assets to the cache; for the dry-run target it writes the manifest to the output writer. A failure here is wrapped as "error closing target" — the work may have been applied but results could not be persisted/reported.

Source

Thrown at upup/pkg/fi/nodeup/command.go:395

	context, err := fi.NewNodeupContext(ctx, target, keyStore, &bootConfig, &nodeupConfig, taskMap)
	if err != nil {
		return fmt.Errorf("error building context: %w", err)
	}

	var options fi.RunTasksOptions
	options.InitDefaults()

	// Return rather than exit, so that the retry loop in cmd/nodeup gets to run:
	// kops-configuration.service is Type=oneshot, so a bootstrap that exits here is never
	// retried and the node never joins the cluster.
	err = context.RunTasks(options)
	if err != nil {
		return fmt.Errorf("error running tasks: %w", err)
	}

	err = target.Finish(taskMap)
	if err != nil {
		return fmt.Errorf("error closing target: %w", err)
	}

	if nodeupConfig.EnableLifecycleHook {
		if bootConfig.CloudProvider == api.CloudProviderAWS {
			err := completeWarmingLifecycleAction(ctx, cloud, modelContext)
			if err != nil {
				return fmt.Errorf("failed to complete lifecylce action: %w", err)
			}
		}
	}
	return nil
}

func getMachineType(ctx context.Context) (string, error) {
	config, err := awsconfig.LoadDefaultConfig(ctx)
	if err != nil {
		return "", fmt.Errorf("failed to load AWS config: %w", err)
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the wrapped error and confirm the cache dir (--cache-dir, default /var/cache/nodeup) is writable and has free space
  2. For dryrun, ensure the output file/pipe is valid and the consumer is still reading
  3. Free disk space or fix permissions on the cache/output paths, then re-run nodeup
  4. Since tasks already ran, verify node state with systemctl/containerd before blindly re-running

Example fix

// before
nodeup --target=dryrun --config=... > /mnt/ro/out.yaml   # /mnt/ro read-only
// after
nodeup --target=dryrun --config=... > /tmp/out.yaml
Defensive patterns

Strategy: validation

Validate before calling

cacheDir := "/var/cache/nodeup"
if info, err := os.Stat(cacheDir); err != nil || !info.IsDir() {
    os.MkdirAll(cacheDir, 0o755)
}
if unix.Access(cacheDir, unix.W_OK) != nil {
    return fmt.Errorf("cache dir %s not writable", cacheDir)
}

Try / catch

if err := nodeupCmd.Run(ctx); err != nil {
    if strings.Contains(err.Error(), "error closing target") {
        log.Fatalf("target finish failed (check cache dir / output file): %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: target.Finish(taskMap) returns an error: for LocalTarget, failures writing to CacheDir; for NodeupDryRunTarget, failures writing to the output stream (closed/broken pipe, unwritable file).

Common situations: --cache-dir points to a read-only or full filesystem; disk full on the node; dry-run output file path unwritable or the pipe consumer exited early (e.g. `nodeup --target dryrun | head` closing stdout).

Related errors


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