juanfont/headscale · error

writing policy: %w

Error message

writing policy: %w

What it means

Produced when hsic.writePolicy(hsic.aclPolicy) fails — only attempted when a policy option (WithACLPolicy) was supplied. The policy is serialized (HuJSON) and written to a file inside the container; failure means serialization of the policy to bytes or the in-container file write failed.

Source

Thrown at integration/hsic/hsic.go:608

	)

	// Write the CA certificates to the container
	for i, cert := range hsic.caCerts {
		err = hsic.WriteFile(fmt.Sprintf("%s/user-%d.crt", caCertRoot, i), cert)
		if err != nil {
			return nil, fmt.Errorf("writing TLS certificate to container: %w", err)
		}
	}

	err = hsic.WriteFile("/etc/headscale/config.yaml", []byte(MinimumConfigYAML()))
	if err != nil {
		return nil, fmt.Errorf("writing headscale config to container: %w", err)
	}

	if hsic.aclPolicy != nil {
		err = hsic.writePolicy(hsic.aclPolicy)
		if err != nil {
			return nil, fmt.Errorf("writing policy: %w", err)
		}
	}

	if hsic.hasTLS() {
		err = hsic.WriteFile(tlsCertPath, hsic.tlsCert)
		if err != nil {
			return nil, fmt.Errorf("writing TLS certificate to container: %w", err)
		}

		err = hsic.WriteFile(tlsKeyPath, hsic.tlsKey)
		if err != nil {
			return nil, fmt.Errorf("writing TLS key to container: %w", err)
		}
	}

	for _, f := range hsic.filesInContainer {
		err := hsic.WriteFile(f.path, f.contents)
		if err != nil {

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Check the wrapped error: marshalling errors point at the policy struct; copy errors point at the container
  2. Simplify the policy to a minimal valid one to isolate the offending field
  3. Confirm the container is running and /etc/headscale writable
  4. Compare with working policies in existing integration tests for the same format
Defensive patterns

Strategy: validation

Validate before calling

// Lint the policy before passing it in
if _, err := policyv2.CompilePolicy(aclPolicy); err != nil { t.Fatalf("invalid policy: %v", err) }

Prevention

When it happens

Trigger: Constructing HeadscaleInContainer with WithACLPolicy(...) where the *tailcfg.Policy or acl.Policy cannot be marshalled (unsupported field combination), or the in-container write fails as in errors 673/674.

Common situations: Test passing a policy struct with fields the serializer does not handle; container not writable; transient docker exec failure.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/db4b992d074b2120. Report an issue: GitHub.