{"record":{"id":"5b490558041f9b77","repo":"juanfont/headscale","slug":"loading-database-policy-on-startup-w","errorCode":null,"errorMessage":"loading database policy on startup: %w","messagePattern":"loading database policy on startup: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"integration/hsic/hsic.go","lineNumber":636,"sourceCode":"\t\terr = hsic.WriteFile(tlsKeyPath, hsic.tlsKey)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"writing TLS key to container: %w\", err)\n\t\t}\n\t}\n\n\tfor _, f := range hsic.filesInContainer {\n\t\terr := hsic.WriteFile(f.path, f.contents)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"writing %q: %w\", f.path, err)\n\t\t}\n\t}\n\n\t// Load the database from policy file on repeat until it succeeds,\n\t// this is done as the container sleeps before starting headscale.\n\tif hsic.aclPolicy != nil && hsic.policyMode == types.PolicyModeDB {\n\t\terr := pool.Retry(hsic.reloadDatabasePolicy)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"loading database policy on startup: %w\", err)\n\t\t}\n\t}\n\n\treturn hsic, nil\n}\n\nfunc (t *HeadscaleInContainer) ConnectToNetwork(network *dockertest.Network) error {\n\treturn t.container.ConnectToNetwork(network)\n}\n\nfunc (t *HeadscaleInContainer) hasTLS() bool {\n\treturn len(t.tlsCert) != 0 && len(t.tlsKey) != 0\n}\n\n// Shutdown stops and cleans up the Headscale container.\nfunc (t *HeadscaleInContainer) Shutdown() (string, string, error) {\n\tstdoutPath, stderrPath, err := t.SaveLog(\"/tmp/control\")\n\tif err != nil {","sourceCodeStart":618,"sourceCodeEnd":654,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/integration/hsic/hsic.go#L618-L654","documentation":"Thrown when pool.Retry(hsic.reloadDatabasePolicy) exhausts its retries. In PolicyModeDB with an aclPolicy set, the policy must be loaded into the database via the container CLI before headscale starts (the container sleeps, then boots). reloadDatabasePolicy runs the load command repeatedly; persistent failure means headscale cannot ingest the policy file.","triggerScenarios":"HeadscaleInContainer built with WithACLPolicy and database policy mode: `headscale policy load` (or equivalent) inside the container keeps failing — invalid HuJSON/ACL syntax, unknown autogroup/tag references, or the headscale binary erroring on the policy — until pool.Retry gives up.","commonSituations":"Policy file with syntax errors or referencing undefined tags/users; policy written to the container (error 675 succeeded) but semantically invalid; version change in policy semantics between headscale releases.","solutions":["Run the load command manually: docker exec <hs> headscale policy load /etc/headscale/acl.hujson ... to see the exact policy error","Validate the policy HuJSON locally against hscontrol/policy/v2 semantics","Check that any tags/users referenced by the policy exist or are declared in the policy itself","If the mode was unintended, use file policy mode instead of PolicyModeDB"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate policy once before container setup\ntmp := t.TempDir() + \"/acl.hujson\"\nos.WriteFile(tmp, serializedPolicy, 0o600)\nif out, err := exec.Command(headscaleBin, \"policy\", \"load\", \"--test\", tmp).CombinedOutput(); err != nil {\n    t.Fatalf(\"policy rejected: %v\\n%s\", err, out)\n}","typeGuard":null,"tryCatchPattern":"if err := pool.Retry(hsic.reloadDatabasePolicy); err != nil {\n    // re-run the load command manually to capture the exact CLI error for the report\n    t.Fatalf(\"policy load failed; policy likely invalid: %v\", err)\n}","preventionTips":["Lint HuJSON policies with headscale policy check/load --test before integration runs","Ensure referenced tags/users exist or are defined within the policy","Track policy-syntax changes when bumping headscale versions"],"tags":["integration-test","policy","database","hujson"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}