{"record":{"id":"9dadeb277ef1176b","repo":"vectordotdev/vector","slug":"file-server-exited-with-an-error","errorCode":null,"errorMessage":"file server exited with an error","messagePattern":"file server exited with an error","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/sources/file.rs","lineNumber":695,"sourceCode":"                }\n                Err(_) => {\n                    let (count, _) = messages.size_hint();\n                    emit!(StreamClosedError { count });\n                }\n            }\n        });\n\n        let span = info_span!(\"file_server\");\n        tokio::task::spawn_blocking(move || {\n            let _enter = span.enter();\n            let rt = tokio::runtime::Handle::current();\n            let result =\n                rt.block_on(file_server.run(tx, shutdown, shutdown_checkpointer, checkpointer));\n            emit!(FileOpen { count: 0 });\n            // Panic if we encounter any error originating from the file server.\n            // We're at the `spawn_blocking` call, the panic will be caught and\n            // passed to the `JoinHandle` error, similar to the usual threads.\n            result.expect(\"file server exited with an error\");\n        })\n        .map_err(|error| error!(message=\"File server unexpectedly stopped.\", %error, internal_log_rate_limit = false))\n        .await\n    })\n}\n\n/// Emit deprecation warning if the old option is used, and take it into account when determining\n/// defaults. Any of the newer options will override it when set directly.\nfn reconcile_position_options(\n    start_at_beginning: Option<bool>,\n    ignore_checkpoints: Option<bool>,\n    read_from: Option<ReadFromConfig>,\n) -> (bool, ReadFrom) {\n    if start_at_beginning.is_some() {\n        warn!(\n            message = \"Use of deprecated option `start_at_beginning`. Please use `ignore_checkpoints` and `read_from` options instead.\"\n        )\n    }","sourceCodeStart":677,"sourceCodeEnd":713,"githubUrl":"https://github.com/vectordotdev/vector/blob/3708c39b12a93212ed8b8d7510b4cc7769cb5864/src/sources/file.rs#L677-L713","documentation":"The file source drives its file server on a blocking thread: rt.block_on(file_server.run(...)) followed by result.expect(\"file server exited with an error\"). FileServer::run returns Err only for errors it treats as terminal rather than per-file logging. The panic is contained by design: spawn_blocking turns it into a JoinHandle error and the surrounding .map_err logs \"File server unexpectedly stopped.\" - but the source task then ends, so log collection stops while the process may keep running.","triggerScenarios":"Any terminal error out of FileServer::run while tailing files - unrecoverable internal failures of the run loop rather than ordinary file read problems; the root-cause error is logged just before this panic.","commonSituations":"data_dir or checkpoint state becoming unwritable (permission changes, disk full, NFS flaps), sharing one data_dir between file sources or instances, or a version regression in the file server run loop.","solutions":["Grep Vector logs for the error immediately preceding 'File server unexpectedly stopped.' and fix that root cause","Check data_dir writability, disk space, and checkpoint file ownership (common after user/permission changes)","Do not share data_dir/checkpoint files between multiple file sources or Vector instances","Patch: replace result.expect(...) with an explicit error log and clean source shutdown; upgrade Vector"],"exampleFix":"// before\nresult.expect(\"file server exited with an error\");\n\n// after\nif let Err(error) = result {\n    error!(message = \"file server exited with an error\", %error, internal_log_rate_limit = false);\n}","handlingStrategy":"try-catch","validationCode":"// preflight before starting the file source:\nlet probe = config.data_dir.join(\".vector_probe\");\nstd::fs::write(&probe, b\"\").context(WriteProbeSnafu)?;\nstd::fs::remove_file(&probe).ok();\n// also verify checkpoint file ownership/permissions if it exists","typeGuard":null,"tryCatchPattern":"// handle the JoinHandle outcome instead of letting the panic vanish into a log line:\nif let Err(join_error) = tokio::task::spawn_blocking(move || {\n    // ... rt.block_on(file_server.run(...)) -> handle Err explicitly\n}).await\n{\n    error!(message = \"File server unexpectedly stopped.\", %join_error);\n    // surface source failure to the supervisor / trigger restart\n}","preventionTips":["Monitor Vector logs for 'File server unexpectedly stopped.' and alert on it, since the process may keep running with a dead file source","Keep data_dir on reliable local storage; avoid NFS for checkpoints","Do not share data_dir between file sources or Vector instances","Watch disk space and permissions on data_dir, especially after user changes"],"tags":["rust","panic","file-source","checkpointing","spawn-blocking"],"backgroundTag":"background-task-panic","analyzedSha":"3708c39b12a93212ed8b8d7510b4cc7769cb5864","analyzedAt":"2026-08-20T07:02:18.786Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}