{"record":{"id":"852538aebc33d61f","repo":"juanfont/headscale","slug":"creating-api-key-w","errorCode":null,"errorMessage":"creating api key: %w","messagePattern":"creating api key: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/headscale/cli/api_key.go","lineNumber":103,"sourceCode":"var createAPIKeyCmd = &cobra.Command{\n\tUse:   \"create\",\n\tShort: \"Creates a new Api key\",\n\tLong: `\nCreates a new Api key, the Api key is only visible on creation\nand cannot be retrieved again.\nIf you lose a key, create a new one and revoke (expire) the old one.`,\n\tAliases: []string{\"c\", cmdNew},\n\tRunE: clientRunE(func(ctx context.Context, client *clientv1.ClientWithResponses, cmd *cobra.Command, args []string) error {\n\t\texpiryTime, err := expirationFromFlag(cmd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tresp, err := client.CreateApiKeyWithResponse(ctx, clientv1.CreateApiKeyJSONRequestBody{\n\t\t\tExpiration: &expiryTime,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"creating api key: %w\", err)\n\t\t}\n\n\t\tif resp.StatusCode() != http.StatusOK {\n\t\t\treturn apiError(resp.StatusCode(), resp.ApplicationproblemJSONDefault)\n\t\t}\n\n\t\treturn printOutput(cmd, resp.JSON200.ApiKey, resp.JSON200.ApiKey)\n\t}),\n}\n\n// apiKeyIDOrPrefix reads --id and --prefix from cmd and validates that\n// exactly one is provided.\nfunc apiKeyIDOrPrefix(cmd *cobra.Command) (uint64, string, error) {\n\tid, _ := cmd.Flags().GetUint64(\"id\")\n\tprefix, _ := cmd.Flags().GetString(\"prefix\")\n\n\tswitch {\n\tcase id == 0 && prefix == \"\":","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/cmd/headscale/cli/api_key.go#L85-L121","documentation":"Wrapped transport error from the 'headscale apikeys create' subcommand: the POST to /api/v1/apikey failed at the HTTP layer (client.CreateApiKeyWithResponse returned err), so no status code or body exists yet. Distinct from an HTTP-level failure, which is reported via apiError instead.","triggerScenarios":"'headscale apikeys create' with the server unreachable, a TLS handshake failure, a context cancellation/timeout, or an invalid API endpoint URL in the CLI socket configuration.","commonSituations":"Server not running or restarted mid-command; cert trust issues between CLI and server; expiry flag producing an invalid request body is NOT this error (that yields an HTTP 4xx via apiError) — this is purely connectivity/transport.","solutions":["Confirm server reachability ('headscale health')","Fix the CLI address/TLS settings to match the server","Retry after the server is stable if it was restarting","Inspect the wrapped error for the precise transport cause (dial tcp, x509, context deadline)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if _, err := client.CreateApiKeyWithResponse(ctx, body); err != nil {\n\tif errors.Is(err, context.DeadlineExceeded) { return err }\n\t// transient dial errors: safe to retry; creation is idempotent-ish only if you de-dup by prefix afterwards\n}","preventionTips":["Check server health before creating keys in automation","Note that a transport-failed create may still have succeeded server-side — list keys to confirm before retrying","Use stable scripts that capture and store the created key or prefix"],"tags":["network","http-client","cli","go"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}