{"record":{"id":"6fc91878510f35c5","repo":"benbjohnson/litestream","slug":"litestream-hydration-file-is-read-only","errorCode":null,"errorMessage":"litestream_hydration_file is read-only","messagePattern":"litestream_hydration_file is read-only","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vfs.go","lineNumber":2494,"sourceCode":"\t\t\treturn nil, err\n\t\t}\n\t\treturn nil, nil\n\n\tcase \"litestream_hydration_progress\":\n\t\tif pragmaValue != nil {\n\t\t\treturn nil, fmt.Errorf(\"litestream_hydration_progress is read-only\")\n\t\t}\n\t\tif f.hydrator == nil {\n\t\t\tresult := \"0\"\n\t\t\treturn &result, nil\n\t\t}\n\t\tpct := f.hydrator.Status().Pct() * 100\n\t\tresult := strconv.FormatFloat(pct, 'f', 1, 64)\n\t\treturn &result, nil\n\n\tcase \"litestream_hydration_file\":\n\t\tif pragmaValue != nil {\n\t\t\treturn nil, fmt.Errorf(\"litestream_hydration_file is read-only\")\n\t\t}\n\t\tresult := f.hydrationPath\n\t\treturn &result, nil\n\n\tcase \"litestream_write_enabled\":\n\t\tif pragmaValue == nil {\n\t\t\t// READ mode - return current state\n\t\t\tf.mu.Lock()\n\t\t\tenabled := f.writeEnabled\n\t\t\tf.mu.Unlock()\n\t\t\tif enabled {\n\t\t\t\tresult := \"1\"\n\t\t\t\treturn &result, nil\n\t\t\t}\n\t\t\tresult := \"0\"\n\t\t\treturn &result, nil\n\t\t}\n\t\t// WRITE mode - enable or disable","sourceCodeStart":2476,"sourceCodeEnd":2512,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/vfs.go#L2476-L2512","documentation":"Litestream's VFS exposes custom SQLite pragmas like litestream_hydration_file to report state. This pragma only supports READ mode; attempting to SET it (PRAGMA litestream_hydration_file='...') is rejected because the hydration path is managed internally by the VFS, never by user configuration at runtime.","triggerScenarios":"Executing `PRAGMA litestream_hydration_file = '/some/path'` (pragmaValue != nil) against a SQLite connection opened with the Litestream VFS.","commonSituations":"Scripts or tools that set all pragmas uniformly at connection setup; ORM connection hooks that blindly apply a pragma list; attempting to redirect hydration to a different file without restarting with a new VFS configuration.","solutions":["Remove the assignment form; use `PRAGMA litestream_hydration_file;` (read-only) to inspect the path","Change the hydration path via VFS file/connection configuration and reopen the database instead of via pragma","If you need a different hydration target, create a new VFS instance with the desired hydrationPath"],"exampleFix":"// before\nconn.Exec(\"PRAGMA litestream_hydration_file = '/tmp/hydrate.db'\")\n// after\nvar path string\nconn.QueryRow(\"PRAGMA litestream_hydration_file\").Scan(&path)","handlingStrategy":"validation","validationCode":"const readOnlyLitestreamPragmas = [\"litestream_hydration_file\", \"litestream_hydration_progress\"];\nfunction isReadOnlyLitestreamPragma(stmt) {\n  return readOnlyLitestreamPragmas.some(p => stmt.toLowerCase().startsWith(`pragma ${p} =`));\n}\nif (isReadOnlyLitestreamPragma(sql)) throw new Error(\"Refusing to execute: pragma is read-only\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never assign to litestream_* pragmas; only query them","Audit connection bootstrap scripts for blanket pragma application","Configure hydration paths in VFS constructor options, not pragmas"],"tags":["sqlite","pragma","read-only"],"backgroundTag":"unsupported-operation","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"}