# Dynamic format strings in Rust: why format! requires a literal

> Understand why Rust format! cannot use a runtime String as its format template, while runtime values still work normally.

HTML: https://rustprint.com/format/runtime-format-strings/

Rust's standard `format!` macro does **not** accept a runtime `String` or variable as the format template. Its first format argument must be a string literal so the compiler can parse and validate the formatting syntax before the program runs.

**A runtime String cannot be used as the format! template**

```rust
fn main() {
    let template = String::from("value={}");
    let value = 42;

    let _output = format!(template, value);
}
```

The compile-fail example above is intentionally rejected by Rust CI. RustPrint checks both that compilation fails and that the compiler reports that the format argument must be a string literal.

## Runtime values are supported

The format template must be a literal, but the values inserted into it can be ordinary runtime values.

**Runtime values inside a compiler-checked format string**

```rust
let value = 42;
let label = String::from("answer");
assert_eq!(format!("{label}={value}"), "answer=42");
```

That distinction is the important one: the **format language** is known at compile time, while the **values being formatted** can come from runtime state.

## Why Rust requires a literal

Rust's formatting macros are compiler-supported. The compiler parses the literal format string and checks that its fields and arguments make sense together.

A runtime string cannot receive that same compile-time validation because its contents are not known when the program is compiled. `format_args!` does not bypass this rule; it also operates on a literal formatting string.

## If the template itself must change at runtime

If users, configuration, files, or another runtime source determine the formatting template, you need a runtime formatting or templating layer rather than the standard `format!` syntax.

RustPrint does not recommend a crate on this page yet. Crate choices change independently of the language and need their own current maintenance, compatibility, and security review. This page documents the standard-library boundary only.

If the format template is fixed and only argument selection, width, or precision varies, stay with the standard formatting system. See [arguments and captured variables](/format/arguments-and-capture/index.md) and [Rust format strings](/format/format-strings/index.md).

## Sources

- [format!](https://doc.rust-lang.org/std/macro.format.html)
- [std::fmt usage](https://doc.rust-lang.org/std/fmt/#usage)

## Related RustPrint guides

- [format! - build a String](/output/format-macro/index.md): Use Rust format! when you need an owned String produced with the standard formatting syntax.
- [Rust format arguments: positional, named, and captured variables](/format/arguments-and-capture/index.md): Use implicit, positional, named, and captured arguments in Rust format strings, including println! with captured variables and how argument selection ends at the colon.
- [Rust format strings - syntax, width, precision, and traits](/format/format-strings/index.md): Read Rust format strings from {} through argument capture, width, precision, alignment, escaping, and formatting traits.
