loco-rs/loco · error

: : ```rust block is never closed

Error message

{}:{}: ```rust block is never closed

What it means

The docs-syntax extractor scans for an opening ```rust fence and then a matching closing fence; this bail fires when the file ends without a closing fence. The unclosed block cannot be delimited, so the file's markdown is malformed and the tool aborts with the path and line of the opening fence.

Solutions

  1. Open the file at the reported line and add the missing closing ``` fence
  2. Run a markdown linter (e.g. markdownlint MD040/unclosed-fence rules) over docs/ to catch other unclosed blocks
  3. Check any script that generates docs to ensure it emits closing fences

Example fix

// before
```rust
fn main() {}
<!-- file ends, no closing fence -->
// after
```rust
fn main() {}
```
Defensive patterns

Strategy: validation

Validate before calling

grep -c '^```rust' file.md; grep -c '^```' file.md # counts must be balanced

Prevention

When it happens

Trigger: A markdown file under docs/ (or a scanned source dir) contains ```` ```rust ```` at a line with no subsequent ```` ``` ```` line before EOF; `collect` recurses into itself and hits this when processing such files.

Common situations: Manual doc edits that truncate a code block; copy/paste that drops the closing fence; merge conflicts partially resolving a fenced block; code-generation scripts that forget the closer.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of loco-rs/loco@23639d1e36 (2026-09-12). Data as JSON: /api/errors/1a5e91cba9aa01d7. Report an issue: GitHub.

Appendix: source

Thrown at xtask/src/docs_syntax.rs:206

                    let reason = reason_at(&lines[opened_at][at + SKIP_MARKER.len()..]);
                    if reason.is_none() {
                        bail!(
                            "{}:{}: `{SKIP_MARKER}` needs a reason — write it as \
                             ```rust {SKIP_MARKER}=\"why this is not Rust\"",
                            path.display(),
                            opened_at + 1
                        );
                    }
                    true
                }
            };
            index += 1;
            let start = index;
            while index < lines.len() && !closing.is_match(lines[index]) {
                index += 1;
            }
            if index >= lines.len() {
                bail!(
                    "{}:{}: ```rust block is never closed",
                    path.display(),
                    opened_at + 1
                );
            }
            out.push(Block {
                file: path.clone(),
                line: opened_at + 1,
                code: lines[start..index.min(lines.len())].join("\n"),
                skipped,
            });
            index += 1;
        }
    }
    Ok(())
}

View on GitHub (pinned to 23639d1e36)