can1357/oh-my-pi · error · MkTempError

too few X's in template {}

Error message

too few X's in template {}

What it means

MkTempError::TooFewXs is raised when the mktemp template contains fewer than the required number of trailing X characters for the random-part replacement (GNU mktemp requires at least 3 X's). The template's trailing X-run is replaced with randomness; too few X's would yield insufficient entropy, so the tool refuses.

Source

Thrown at crates/pi-builtins/src/mktemp.rs:60

static ARG_TEMPLATE: &str = "template";

#[cfg(not(windows))]
const TMPDIR_ENV_VAR: &str = "TMPDIR";
#[cfg(windows)]
const TMPDIR_ENV_VAR: &str = "TMP";

const FALLBACK_TMPDIR: &str = "/tmp";

#[derive(Error, Debug)]
enum MkTempError {
	#[error("could not persist file {}", .0.quote())]
	Persist(PathBuf),

	#[error("with --suffix, template {} must end in X", .0.quote())]
	MustEndInX(String),

	#[error("too few X's in template {}", .0.quote())]
	TooFewXs(String),

	#[error("invalid template, {}, contains directory separator", .0.quote())]
	PrefixContainsDirSeparator(String),

	#[error("invalid suffix {}, contains directory separator", .0.quote())]
	SuffixContainsDirSeparator(String),

	#[error("invalid template, {}; with --tmpdir, it may not be absolute", .0.quote())]
	InvalidTemplate(OsString),

	#[error("too many templates")]
	TooManyTemplates,

	#[error("failed to create {} via template {}: No such file or directory", .0, .1.quote())]
	NotFound(String, PathBuf),

	#[error(transparent)]

View on GitHub (pinned to 9690622007)

Solutions

  1. Use at least 3 trailing X's, e.g. `mktemp XXXXXX` (more X's = more entropy)
  2. Generate templates programmatically with a fixed X-run of sufficient length
  3. If only one random file is needed, more X's are still cheap — use 6+ for safety
  4. Avoid tools/internal helpers that pass user input through as the template without validating X count

Example fix

// before
mktemp tmpXX
// after
mktemp tmpXXXXXX
Defensive patterns

Strategy: validation

Validate before calling

const xs = (t: string): number => (t.match(/X+$/) ?? [''])[0].length;
if (xs(template) < 3) {
  throw new RangeError(`too few X's in template '${template}': need at least 3 trailing X's`);
}

Type guard

const hasEnoughXs = (t: string): boolean => (t.match(/X+$/) ?? [''])[0].length >= 3;

Try / catch

try {
  await Bun.$`mktemp ${tmpl}`.quiet();
} catch (e) {
  if (String(e).includes("too few X's")) {
    await Bun.$`mktemp ${tmpl.replace(/X*$/, 'XXXXXX')}`.quiet(); // pad to 6 X's
  } else throw e;
}

Prevention

When it happens

Trigger: `mktemp tmp` or `mktemp fooX` — templates with fewer than 3 trailing X's; programmatically built templates where a loop generated only 1–2 X's.

Common situations: Hand-written templates like `mktemp file.XX`; code that strips or truncates X's by accident; porting from tools that accept fewer X's and pad internally (GNU does not).

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/581d1c58d6da5c55. Report an issue: GitHub.