Skip to content

fix: filter empty segments in colon-separated env var parsing#9076

Merged
jdx merged 3 commits intojdx:mainfrom
KnickKnackLabs:baby-joel/empty-override-config-filenames
Apr 14, 2026
Merged

fix: filter empty segments in colon-separated env var parsing#9076
jdx merged 3 commits intojdx:mainfrom
KnickKnackLabs:baby-joel/empty-override-config-filenames

Conversation

@baby-joel
Copy link
Copy Markdown
Contributor

Problem

MISE_OVERRIDE_CONFIG_FILENAMES=""\ (empty string) causes mise to panic:

The application panicked (crashed).
Message: called `Option::unwrap()` on a `None` value
Location: src/config/config_file/config_root.rs:49

When the env var is set to an empty string, split(':') produces [""] — a set with one empty-string entry. This non-empty set replaces the default config filename list, injecting "" as a config path. During Config::load, the empty path absolutizes to the filesystem root (/), which has no parent directory, causing config_root() to panic on path.parent().unwrap().

How this happens in practice

vfox plugins that spawn nested mise processes (e.g., mise -C <plugin-path> run install) inherit the parent's MISE_OVERRIDE_CONFIG_FILENAMES. When the parent sets it to mise.ci.toml, the child process looks for a non-existent mise.ci.toml in the plugin directory. Unsetting it via VAR='' command is a common workaround — but the empty string triggers this panic.

Fix

Add .filter(|s| !s.is_empty()) to both colon-split expressions in src/env.rs:

  • MISE_OVERRIDE_CONFIG_FILENAMES
  • MISE_OVERRIDE_TOOL_VERSIONS_FILENAMES

This also correctly handles edge cases like trailing/leading colons (:mise.ci.toml:) and consecutive colons.

Tests

  • e2e test: test_override_config_filenames_empty — verifies empty string, colon-only, and leading/trailing colons all work without panicking
  • unit test: test_split_colon_filters_empty_segments — documents the correct filter pattern for all edge cases

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses a potential panic when environment variables like MISE_OVERRIDE_CONFIG_FILENAMES are set to empty strings or contain empty segments. The fix involves filtering out empty strings after splitting by colons in src/env.rs. Additionally, a new e2e regression test and a unit test have been added to ensure correct behavior for various edge cases. I have no feedback to provide.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 13, 2026

Greptile Summary

This PR fixes a panic in config_root() triggered when MISE_OVERRIDE_CONFIG_FILENAMES=\"\" is set to an empty string. The fix extracts a split_colon_list helper that filters empty segments produced by empty strings, leading/trailing colons, or consecutive colons, and applies it to both MISE_OVERRIDE_CONFIG_FILENAMES and MISE_OVERRIDE_TOOL_VERSIONS_FILENAMES in src/env.rs.

Confidence Score: 5/5

Safe to merge — the fix is minimal, correct, and well-tested; no P0/P1 issues found.

The panic fix is verified by tracing from split_colon_list through the is_empty() guard in config/mod.rs. Unit and e2e tests cover the key edge cases. All remaining observations are P2.

No files require special attention.

Important Files Changed

Filename Overview
src/env.rs Extracts split_colon_list helper that filters empty segments; applied correctly to both override filename env vars. Unit test covers all edge cases.
e2e/config/test_override_config_filenames_empty Adds regression e2e test covering empty string, colon-only, and leading/trailing colon cases for MISE_OVERRIDE_CONFIG_FILENAMES; no test for the parallel MISE_OVERRIDE_TOOL_VERSIONS_FILENAMES fix (flagged in a prior comment).

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["env var set? (e.g. MISE_OVERRIDE_CONFIG_FILENAMES)"] -->|"Err (unset)"| B["miserc fallback / unwrap_or_default\n→ empty IndexSet"]
    A -->|"Ok(v) == 'none'"| C["Some(empty IndexSet)"]
    A -->|"Ok(v)"| D["split_colon_list(v)"]
    D --> E["split(':')"]
    E --> F["filter empty segments"]
    F --> G["collect → IndexSet"]
    G --> H{{"is_empty()?"}}
    B --> H
    H -->|"true"| I["use default config filenames\n(.config/mise/config.toml, mise.toml, …)"]
    H -->|"false"| J["use override filenames only"]
Loading

Reviews (4): Last reviewed commit: "[autofix.ci] apply automated fixes" | Re-trigger Greptile

@baby-joel baby-joel force-pushed the baby-joel/empty-override-config-filenames branch from 7fe9e8e to 7ae76d1 Compare April 13, 2026 21:26
Comment thread e2e/config/test_override_config_filenames_empty Outdated
Comment thread e2e/config/test_override_config_filenames_empty
@baby-joel baby-joel force-pushed the baby-joel/empty-override-config-filenames branch from 7ae76d1 to 4414ec2 Compare April 13, 2026 21:28
When MISE_OVERRIDE_CONFIG_FILENAMES is set to an empty string,
split(':') produces [""] — a set containing one empty string.
This non-empty set replaces the default config filename list,
injecting "" as a config path. During Config::load, this empty
path reaches config_root() which panics on path.parent().unwrap()
because the absolutized empty string resolves to the filesystem
root (/).

The e2e test reproduces the exact panic seen in CI when vfox
plugins spawn nested mise processes that inherit the parent's
MISE_OVERRIDE_CONFIG_FILENAMES.

Also adds a unit test documenting the correct filter pattern.
MISE_OVERRIDE_CONFIG_FILENAMES and MISE_OVERRIDE_TOOL_VERSIONS_FILENAMES
split their values on ':' but don't filter empty segments. When set to
an empty string (e.g., by a parent process clearing it via VAR='' cmd),
split(':') produces [""] — a one-element set containing an empty string.

This non-empty set replaces the default config filename list and injects
"" as a config path. During Config::load, the empty path absolutizes to
the filesystem root, which has no parent directory, causing config_root()
to panic on path.parent().unwrap().

Extract split_colon_list() helper that filters empty segments. Both env
vars now use it. Also handles trailing/leading colons and consecutive
colons gracefully.
@baby-joel baby-joel force-pushed the baby-joel/empty-override-config-filenames branch from 4414ec2 to f085403 Compare April 13, 2026 21:31
@jdx jdx merged commit 5188f41 into jdx:main Apr 14, 2026
34 checks passed
mise-en-dev added a commit that referenced this pull request Apr 15, 2026
### 🚀 Features

- **(npm)** use --min-release-age for npm 11.10.0+ supply chain
protection by @webkaz in [#9072](#9072)
- **(registry)** add openfga by @mnm364 in
[#9084](#9084)
- **(task)** allow to set confirmation default by @roele in
[#9089](#9089)
- support os/arch compound syntax in tool os filtering by @RobertDeRose
in [#9088](#9088)

### 🐛 Bug Fixes

- **(activate)** export __MISE_EXE and resolve bare ARGV0 to absolute
path by @fru1tworld in [#9081](#9081)
- **(install)** support aliased installs sharing a backend by @jdx in
[#9093](#9093)
- **(shim)** use which_no_shims when resolving mise binary in reshim and
doctor by @kevinswiber in [#9071](#9071)
- filter empty segments in colon-separated env var parsing by @baby-joel
in [#9076](#9076)

### 📚 Documentation

- fix wrong file reference to forgejo backend implemenation by @roele in
[#9090](#9090)
- fix cli token command for token resolution by @roele in
[#9077](#9077)

### 📦 Registry

- add trzsz-go
([aqua:trzsz/trzsz-go](https://github.com/trzsz/trzsz-go)) by
@ZeroAurora in [#9083](#9083)
- add copilot
([aqua:github/copilot-cli](https://github.com/github/copilot-cli)) by
@risu729 in [#9082](#9082)

### Chore

- add AGENTS.md symlink by @jdx in
[#9094](#9094)

### New Contributors

- @kevinswiber made their first contribution in
[#9071](#9071)
- @webkaz made their first contribution in
[#9072](#9072)
- @RobertDeRose made their first contribution in
[#9088](#9088)

## 📦 Aqua Registry Updates

#### New Packages (7)

-
[`IBM-Cloud/ibm-cloud-cli-release`](https://github.com/IBM-Cloud/ibm-cloud-cli-release)
- [`max-sixty/worktrunk`](https://github.com/max-sixty/worktrunk)
- [`micelio.dev/hif`](https://github.com/micelio.dev/hif)
- [`pgplex/pgschema`](https://github.com/pgplex/pgschema)
-
[`rose-pine/rose-pine-bloom`](https://github.com/rose-pine/rose-pine-bloom)
- [`santosr2/TerraTidy`](https://github.com/santosr2/TerraTidy)
- [`trzsz/trzsz-go`](https://github.com/trzsz/trzsz-go)

#### Updated Packages (3)

- [`mvdan/sh`](https://github.com/mvdan/sh)
- [`rvben/rumdl`](https://github.com/rvben/rumdl)
- [`temporalio/temporal`](https://github.com/temporalio/temporal)
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Apr 16, 2026
## [2026.4.14](https://github.com/jdx/mise/compare/v2026.4.13..v2026.4.14) - 2026-04-15

### Chore

- bump sigstore-verification by @jdx in [#9128](jdx/mise#9128)

## [2026.4.13](https://github.com/jdx/mise/compare/v2026.4.12..v2026.4.13) - 2026-04-15

### 🐛 Bug Fixes

- **(go)** honor install_before for module versions by @mariusvniekerk in [#9097](jdx/mise#9097)
- **(vfox-plugin)** support Git URL with commit hash for mise.toml by @Oyami-Srk in [#9099](jdx/mise#9099)
- `MISE_FETCH_REMOTE_VERSIONS_CACHE` not respected by @mcncl in [#9096](jdx/mise#9096)

### 📦️ Dependency Updates

- unblock cargo-deny advisories check by @jdx in [#9112](jdx/mise#9112)

### New Contributors

- @mariusvniekerk made their first contribution in [#9097](jdx/mise#9097)
- @mcncl made their first contribution in [#9096](jdx/mise#9096)
- @Oyami-Srk made their first contribution in [#9099](jdx/mise#9099)

## [2026.4.12](https://github.com/jdx/mise/compare/v2026.4.11..v2026.4.12) - 2026-04-15

### 🚀 Features

- **(npm)** use --min-release-age for npm 11.10.0+ supply chain protection by @webkaz in [#9072](jdx/mise#9072)
- **(registry)** add openfga by @mnm364 in [#9084](jdx/mise#9084)
- **(task)** allow to set confirmation default by @roele in [#9089](jdx/mise#9089)
- support os/arch compound syntax in tool os filtering by @RobertDeRose in [#9088](jdx/mise#9088)

### 🐛 Bug Fixes

- **(activate)** export __MISE_EXE and resolve bare ARGV0 to absolute path by @fru1tworld in [#9081](jdx/mise#9081)
- **(install)** support aliased installs sharing a backend by @jdx in [#9093](jdx/mise#9093)
- **(shim)** use which_no_shims when resolving mise binary in reshim and doctor by @kevinswiber in [#9071](jdx/mise#9071)
- filter empty segments in colon-separated env var parsing by @baby-joel in [#9076](jdx/mise#9076)

### 📚 Documentation

- fix wrong file reference to forgejo backend implemenation by @roele in [#9090](jdx/mise#9090)
- fix cli token command for token resolution by @roele in [#9077](jdx/mise#9077)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants