{"record":{"id":"12bdc23dd6ce218f","repo":"benbjohnson/litestream","slug":"failed-to-expand-meta-dir-for-s-w","errorCode":null,"errorMessage":"failed to expand meta dir for %s: %w","messagePattern":"failed to expand meta dir for (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/litestream/main.go","lineNumber":889,"sourceCode":"\t\treturn nil, fmt.Errorf(\"failed to calculate relative path for %s: %w\", dbPath, err)\n\t}\n\n\t// Create a copy of the config for the discovered database\n\tdbConfigCopy := *dbc\n\tdbConfigCopy.Path = dbPath\n\tdbConfigCopy.Dir = \"\"          // Clear dir field for individual DB\n\tdbConfigCopy.Pattern = \"\"      // Clear pattern field\n\tdbConfigCopy.Recursive = false // Clear recursive flag\n\tdbConfigCopy.Watch = false     // Individual DBs do not watch directories\n\n\t// Ensure every database discovered beneath a directory receives a unique\n\t// metadata path. Without this, all databases share the same meta-path and\n\t// clobber each other's replication state.\n\tswitch {\n\tcase dbc.MetaDir != nil:\n\t\tbaseMetaDir, err := expand(*dbc.MetaDir)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to expand meta dir for %s: %w\", dbPath, err)\n\t\t}\n\t\tmetaPathCopy := filepath.Join(baseMetaDir, relPath+litestream.MetaDirSuffix)\n\t\tdbConfigCopy.MetaPath = &metaPathCopy\n\t\tdbConfigCopy.MetaDir = nil\n\tcase dbc.MetaPath != nil:\n\t\tbaseMetaPath, err := expand(*dbc.MetaPath)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to expand meta path for %s: %w\", dbPath, err)\n\t\t}\n\t\tmetaPathCopy := deriveMetaPathForDirectoryEntry(baseMetaPath, relPath)\n\t\tdbConfigCopy.MetaPath = &metaPathCopy\n\t\tdbConfigCopy.MetaDir = nil\n\t}\n\n\t// Deep copy replica config and make path unique per database.\n\t// This prevents all databases from writing to the same replica path.\n\tif dbc.Replica != nil {\n\t\treplicaCopy, err := cloneReplicaConfigWithRelativePath(dbc.Replica, relPath)","sourceCodeStart":871,"sourceCodeEnd":907,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/cmd/litestream/main.go#L871-L907","documentation":"When 'meta-dir' is set, newDBFromDirectoryEntry expands environment variables in it to get the base metadata directory before appending each database's relative path. If the expand step fails, the error is wrapped with the database path being processed.","triggerScenarios":"expand(*dbc.MetaDir) returns an error — typically an unset or malformed environment variable reference (e.g. `meta-dir: $LITESTREAM_META` with LITESTREAM_META undefined, depending on expand's rules).","commonSituations":"Config template uses $VAR expansion but the environment variable isn't set in the service environment; running under systemd without an Environment= entry; variable typo.","solutions":["Set the referenced environment variable in the environment where litestream runs.","Or replace the $VAR reference in meta-dir with a literal absolute path.","Check the wrapped inner error to see which variable failed to expand."],"exampleFix":"# before\nmeta-dir: $LITESTREAM_META_DIR\n\n# after (or export LITESTREAM_META_DIR in the service unit)\nmeta-dir: /var/lib/litestream/meta","handlingStrategy":"validation","validationCode":"if v := os.Getenv(\"LITESTREAM_META_DIR\"); v == \"\" && strings.Contains(metaDir, \"$LITESTREAM_META_DIR\") {\n    return fmt.Errorf(\"LITESTREAM_META_DIR must be set\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set all $VARs used in the config via systemd Environment= or the container env.","Prefer literal paths when the config is deployed to fixed locations.","Log/echo the expanded config at startup in staging."],"tags":["config","litestream","env-var","expansion"],"backgroundTag":"invalid-env-var-value","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}