{"record":{"id":"e4d46530a06e1ab3","repo":"JuliusBrussee/caveman","slug":"postgres-s-must-point-to-a-regular-file","errorCode":null,"errorMessage":"postgres: %s must point to a regular file","messagePattern":"postgres: (.+?) must point to a regular file","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/postgresconfig/postgresconfig.go","lineNumber":93,"sourceCode":"\t}\n\treturn config, nil\n}\n\nfunc caPEMFromEnvironment() (string, error) {\n\tfilePath := strings.TrimSpace(os.Getenv(caFileEnvironment))\n\tdirect := strings.TrimSpace(os.Getenv(caEnvironment))\n\tif filePath != \"\" && direct != \"\" {\n\t\treturn \"\", fmt.Errorf(\"postgres: set only %s or %s, not both\", caFileEnvironment, caEnvironment)\n\t}\n\tif filePath == \"\" {\n\t\treturn direct, nil\n\t}\n\tinfo, err := os.Stat(filePath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"postgres: %s: %w\", caFileEnvironment, err)\n\t}\n\tif !info.Mode().IsRegular() {\n\t\treturn \"\", fmt.Errorf(\"postgres: %s must point to a regular file\", caFileEnvironment)\n\t}\n\tcontents, err := os.ReadFile(filePath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"postgres: read %s: %w\", caFileEnvironment, err)\n\t}\n\treturn strings.TrimSpace(string(contents)), nil\n}\n\n// NewPool constructs a pool from the hardened configuration.\nfunc NewPool(ctx context.Context, databaseURL string) (*pgxpool.Pool, error) {\n\tconfig, err := ParsePoolConfig(databaseURL)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn pgxpool.NewWithConfig(ctx, config)\n}\n\n// NewRuntimePool constructs a pool and proves the connected login is a","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/postgresconfig/postgresconfig.go#L75-L111","documentation":"Error from caPEMFromEnvironment: the path set in the CA-file environment variable exists but is not a regular file (directory, device, fifo). Only a readable regular file can be loaded as a PEM CA bundle, so other file modes are rejected.","triggerScenarios":"The CA-file env var points at a directory (common typo: trailing path to a folder of certs) or at a non-regular filesystem object.","commonSituations":"Pointing the variable at /etc/ssl/certs (a directory) instead of a specific .crt file; using a named pipe set up by an init container; bind-mounting a directory where a file was expected.","solutions":["Point the env var at a specific regular certificate file, e.g. /etc/ssl/certs/ca.crt, not a directory.","If you have multiple CAs, concatenate them into one PEM bundle file.","Verify with `test -f \"$POSTGRES_CA_FILE\"` before starting the service."],"exampleFix":"// before\nexport POSTGRES_CA_FILE=/etc/ssl/certs // a directory\n// after\nexport POSTGRES_CA_FILE=/etc/ssl/certs/ca-certificates.crt","handlingStrategy":"validation","validationCode":"if info, err := os.Stat(os.Getenv(\"POSTGRES_CA_FILE\")); err == nil && !info.Mode().IsRegular() {\n\treturn errors.New(\"POSTGRES_CA_FILE must be a regular file, not a directory\")\n}","typeGuard":null,"tryCatchPattern":"if err := postgresconfig.ValidateTenantSchema(ctx, pool); err != nil {\n\tif strings.Contains(err.Error(), \"must point to a regular file\") { /* fix path config */ }\n}","preventionTips":["Point CA vars at specific .crt/.pem files, never directories.","Concatenate multiple CAs into one bundle file.","Add `test -f \"$POSTGRES_CA_FILE\"` to entrypoint scripts."],"tags":["postgres","tls","file","config"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}