xai-org/grok-build · error

deny glob {glob:?}: empty path segment (a doubled '//' or tr

Error message

deny glob {glob:?}: empty path segment (a doubled '//' or trailing '/'); remove the extra slash in sandbox.toml

What it means

validate_deny_glob rejects deny globs containing empty path segments — doubled slashes (`a//b`) or trailing slashes (`a/`) — because globset keeps `//` literal while the macOS regex collapses it, causing cross-platform divergence. Only a single leading `/` (absolute-path anchor) is permitted to be an 'empty' segment.

Source

Thrown at crates/codegen/xai-grok-sandbox/src/deny/glob.rs:92

/// 2. Compile through `globset` (the Linux matcher) so a malformed glob (`a**b`,
///    unterminated `[`) fails closed identically on both platforms.
#[cfg(all(feature = "enforce", unix))]
pub(crate) fn validate_deny_glob(glob: &str) -> anyhow::Result<()> {
    if let Some(c) = glob.chars().find(|&c| matches!(c, '{' | '}' | '\\')) {
        anyhow::bail!(
            "deny glob {glob:?} uses unsupported metacharacter '{c}' \
             (brace alternation and backslash-escapes are not supported; \
             use separate deny entries)"
        );
    }
    // `**` must be a whole path component (gitignore semantics). A non-component
    // `**` (e.g. `a**b`) would translate to `.*` on macOS but collapse to `*` in
    // globset — reject it on both platforms so they never diverge. Empty
    // segments (`a//*`) drift the same way: globset keeps `//` literally while
    // the macOS regex collapses it.
    for (index, segment) in glob.split('/').enumerate() {
        if segment.is_empty() && !(index == 0 && glob.starts_with('/')) {
            anyhow::bail!(
                "deny glob {glob:?}: empty path segment (a doubled '//' or \
                 trailing '/'); remove the extra slash in sandbox.toml"
            );
        }
        // `.`/`..` would let a relative glob scan outside the workspace on
        // Linux while the macOS regex stays dead; reject on both platforms.
        if segment == "." || segment == ".." {
            anyhow::bail!(
                "deny glob {glob:?}: `.` and `..` segments are not supported; \
                 write the path without them (use an absolute path to deny \
                 files outside the workspace)"
            );
        }
        if segment.contains("**") && segment != "**" {
            anyhow::bail!(
                "deny glob {glob:?}: `**` must be its own path segment (got {segment:?}); \
                 write it as `**/` or `/**`, e.g. `a/**/b`"
            );

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Remove the doubled or trailing slash from the glob in sandbox.toml.
  2. If generating globs programmatically, join path components with a normalizing joiner that collapses separators.
  3. Keep an optional single leading `/` for absolute globs — that is the only allowed empty segment.

Example fix

// before (sandbox.toml)
deny = ["/tmp//secrets/**", "var/log/"]
// after
deny = ["/tmp/secrets/**", "var/log"]
Defensive patterns

Strategy: validation

Validate before calling

fn deny_glob_segments_ok(glob: &str) -> bool {
    glob.split('/').enumerate().all(|(i, seg)| {
        !seg.is_empty() || (i == 0 && glob.starts_with('/'))
    })
}
for g in &deny_globs {
    assert!(deny_glob_segments_ok(g), "empty path segment in deny glob: {g}");
}

Prevention

When it happens

Trigger: A deny glob in sandbox.toml such as `/tmp//x`, `foo/bar/`, or any string where glob.split('/') yields an empty segment that is not the leading absolute-path position.

Common situations: Concatenating path strings in config generation (prefix + `/` + path where path already starts with `/`); hand-edited globs with trailing slashes; template rendering producing doubled separators.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/b2bf161e7d7e803d. Report an issue: GitHub.