linera-io/linera-protocol · warning

cannot have both a json string and file

Error message

cannot have both a json string and file

What it means

read_json() accepts a JSON value either as an inline string or as a file path, but not both. When both Some(string) and Some(path) are supplied, it immediately bails. This helper backs CLI options like --json-grammar-parameter / --parameters <json|file> style pairs, so passing an inline value and a file in the same invocation is rejected before parsing.

Source

Thrown at linera-service/src/cli/main.rs:146

        attempt += 1;
        match operation().await {
            Ok(result) => return Ok(result),
            Err(err) if attempt < max_retries && is_retryable_error(&err) => {
                let backoff_ms = 100 * 2_u64.pow(attempt - 1);
                warn!(
                    "Faucet operation failed with retryable error (attempt {}/{}): {:?}. Retrying after {}ms",
                    attempt, max_retries, err, backoff_ms
                );
                tokio::time::sleep(Duration::from_millis(backoff_ms)).await;
            }
            Err(err) => return Err(err),
        }
    }
}

fn read_json(string: Option<String>, path: Option<PathBuf>) -> anyhow::Result<Vec<u8>> {
    let value = match (string, path) {
        (Some(_), Some(_)) => bail!("cannot have both a json string and file"),
        (Some(s), None) => serde_json::from_str(&s)?,
        (None, Some(path)) => {
            let s = fs_err::read_to_string(path)?;
            serde_json::from_str(&s)?
        }
        (None, None) => Value::Null,
    };
    Ok(serde_json::to_vec(&value)?)
}

#[async_trait]
impl Runnable for Job {
    type Output = anyhow::Result<()>;

    async fn run<S>(self, storage: S) -> anyhow::Result<()>
    where
        S: Storage + Clone + Send + Sync + 'static,
    {

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Remove one of the two inputs — keep either the inline JSON string or the file path, not both.
  2. In wrapper scripts, make the flags mutually exclusive: only forward the file when no inline string is given.
  3. If you meant to merge two JSON documents, merge them yourself first and pass a single source.

Example fix

# before
$ linera ... --json-parameters '{"a":1}' --json-parameters-path params.json
Error: cannot have both a json string and file

# after
$ linera ... --json-parameters-path params.json
# or
$ linera ... --json-parameters '{"a":1}'
Defensive patterns

Strategy: validation

Validate before calling

// In wrappers, enforce exclusivity before invoking the CLI:
if json_string.is_some() && json_path.is_some() {
    anyhow::bail!("pass either the inline JSON or the file, not both");
}

Try / catch

match read_json(string, path).await {
    Ok(bytes) => bytes,
    Err(e) if e.to_string().contains("cannot have both") => {
        // user error: drop one input and re-run; no retry helps
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Invoking a linera CLI command with both the inline JSON option and its file variant populated, e.g. --some-json '{"a":1}' --some-json-path file.json (per the command's declared options), or a wrapper script always forwarding both flags.

Common situations: Copy-pasted command lines where a previous flag was left in; scripts that unconditionally pass a default file plus a user-supplied string; shell aliases appending extra options.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/290ca7b8fb6a4910. Report an issue: GitHub.