can1357/oh-my-pi · error · MkTempError
with --suffix, template {} must end in X
Error message
with --suffix, template {} must end in X What it means
MkTempError::MustEndInX is raised by the builtin `mktemp` when --suffix is supplied but the template does not end in X (after accounting for the suffix). With --suffix, GNU mktemp requires the X-run to terminate the template portion so it can correctly splice the generated random characters before the suffix. This prevents ambiguous or corrupted filenames.
Source
Thrown at crates/pi-builtins/src/mktemp.rs:57
static OPT_TMPDIR: &str = "tmpdir";
static OPT_P: &str = "p";
static OPT_T: &str = "t";
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())]View on GitHub (pinned to 9690622007)
Solutions
- End the template with X's right before the suffix: `mktemp --suffix=.txt XXXXXX`
- Move trailing non-X characters out of the template into --suffix
- Drop --suffix and embed the whole pattern manually if a non-X tail is truly needed (then the X-run must still be at the end)
- Ensure no whitespace or hidden characters trail the X-run in the template
Example fix
// before mktemp --suffix=.log fooXXXXbar // after mktemp --suffix=.log fooXXXX
Defensive patterns
Strategy: validation
Validate before calling
function checkSuffixTemplate(template: string, hasSuffix: boolean): void {
if (hasSuffix && !/X[^X]*$/.test(template) === false) {
// with --suffix the template portion must END in X
}
if (hasSuffix && !template.endsWith('X')) {
throw new RangeError(`with --suffix, template '${template}' must end in X`);
}
} Type guard
const endsInX = (t: string): boolean => t.endsWith('X'); Try / catch
try {
await Bun.$`mktemp --suffix=${suffix} ${tmpl}`.quiet();
} catch (e) {
if (String(e).includes('must end in X')) {
// move trailing non-X chars into the suffix and retry
await Bun.$`mktemp --suffix=${tail + suffix} ${tmpl.replace(/[^X]+$/, '')}`.quiet();
} else throw e;
} Prevention
- When using --suffix, always terminate the template with an X-run
- Keep the X-run and suffix as separate variables, never concatenate first
- Build templates via a helper that enforces the X-suffix boundary
- Review templates after refactors that append extensions
When it happens
Trigger: Calling `mktemp --suffix=.txt fooXXXXbar` where the template part doesn't end in X, or `mktemp --suffix=.log templateXXextra`.
Common situations: Moving from plain `mktemp fooXXXXXX` to suffixed form without realizing the X-run must end at the template/suffix boundary; building templates dynamically where the suffix got merged into the template string.
Related errors
- too few X's in template {}
- invalid template, {}; with --tmpdir, it may not be absolute
- unknown file type: {value}
- invalid size: {value}
- 2
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/017b21cc700b5cb5.
Report an issue: GitHub.