{"record":{"id":"a03fe71fb5baed66","repo":"quickwit-oss/quickwit","slug":"stdin-can-only-be-used-as-source-through-the-cli-c","errorCode":null,"errorMessage":"stdin can only be used as source through the CLI command `quickwit tool local-ingest`","messagePattern":"stdin can only be used as source through the CLI command `quickwit tool local-ingest`","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-config/src/source_config/serialize.rs","lineNumber":108,"sourceCode":"\nimpl SourceConfigForSerialization {\n    /// Checks the validity of the `SourceConfig` as a \"deserializable source\".\n    ///\n    /// Two remarks:\n    /// - This does not check connectivity, it just validate configuration, without performing any\n    ///   IO. See `check_connectivity(..)`.\n    /// - This is used each time the `SourceConfig` is deserialized (at creation but also during\n    ///   communications with the metastore). When ingesting from stdin, we programmatically create\n    ///   an invalid `SourceConfig` and only use it locally.\n    fn validate_and_build(self) -> anyhow::Result<SourceConfig> {\n        if !RESERVED_SOURCE_IDS.contains(&self.source_id.as_str()) {\n            validate_identifier(\"source\", &self.source_id)?;\n        }\n        let num_pipelines = NonZeroUsize::new(self.num_pipelines)\n            .ok_or_else(|| anyhow::anyhow!(\"`desired_num_pipelines` must be strictly positive\"))?;\n        match &self.source_params {\n            SourceParams::Stdin => {\n                bail!(\n                    \"stdin can only be used as source through the CLI command `quickwit tool \\\n                     local-ingest`\"\n                );\n            }\n            SourceParams::File(_)\n            | SourceParams::Kafka(_)\n            | SourceParams::Kinesis(_)\n            | SourceParams::Pulsar(_) => {\n                // TODO consider any validation opportunity\n            }\n            SourceParams::PubSub(_)\n            | SourceParams::Ingest\n            | SourceParams::IngestApi\n            | SourceParams::IngestCli\n            | SourceParams::Vec(_)\n            | SourceParams::Void(_) => {}\n        }\n        match &self.source_params {","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-config/src/source_config/serialize.rs#L90-L126","documentation":"The stdin source is only meaningful when documents are piped into the `quickwit tool local-ingest` CLI command. When a source config is loaded from user config or a source update (`validate_and_build`), a `SourceParams::Stdin` config is rejected because stdin has no meaning for a running cluster-managed source. The loader bails to prevent nonsensical persistent source definitions.","triggerScenarios":"Defining a source in an index config (or via the source config update API/CLI) with `source_type: stdin` and loading it through `load_source_config_from_user_config` or `load_source_config_update`.","commonSituations":"Copy-pasting an example ingest config that used stdin for `quickwit tool local-ingest` into an index's source_configs; trying to run a server-managed stdin source in docker.","solutions":["Remove the stdin source config from the index; use it only as a transient source for `quickwit tool local-ingest --stdin`.","Replace it with a real source type (file, kafka, kinesis, pulsar, gcp-pubsub) appropriate for your ingestion.","For one-off local ingestion, pipe documents: `cat docs.json | quickwit tool local-ingest --index ...` with a stdin source config passed only to the CLI."],"exampleFix":"# before\nsource_configs:\n  - source_id: stdin-src\n    source_type: stdin\n\n# after\nsource_configs:\n  - source_id: my-file-source\n    source_type: file\n    params:\n      path: /data/docs.json","handlingStrategy":"validation","validationCode":"if source_config.source_params == SourceParams::Stdin && !running_local_ingest_cli {\n    return Err(anyhow!(\n        \"stdin source is only valid for `quickwit tool local-ingest`\"\n    ));\n}","typeGuard":"fn is_persistable(params: &SourceParams) -> bool {\n    !matches!(params, SourceParams::Stdin)\n}","tryCatchPattern":"match load_source_config_from_user_config(&user_config) {\n    Ok(sc) => persist(sc),\n    Err(e) if e.to_string().contains(\"local-ingest\") => {\n        eprintln!(\"use `quickwit tool local-ingest` for stdin sources\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never place a stdin source in index source_configs intended for a cluster.","Reserve stdin configs for ad-hoc `quickwit tool local-ingest` invocations only.","Lint index configs to reject `source_type: stdin` outside CLI examples."],"tags":["rust","config","quickwit"],"backgroundTag":"incompatible-source-type","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}