can1357/oh-my-pi · error · MkTempError

invalid suffix {}, contains directory separator

Error message

invalid suffix {}, contains directory separator

What it means

MkTempError::SuffixContainsDirSeparator is raised when the value passed to --suffix contains a directory separator ('/'). The suffix is appended to the generated filename; a slash would imply a nested path that mktemp will not create, so it rejects the argument up front.

Source

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

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)]
	Io(#[from] io::Error),
}

/// Options parsed from the command line.
///
/// This provides a layer of indirection between the application logic and

View on GitHub (pinned to 9690622007)

Solutions

  1. Remove any '/' from the --suffix value; use only plain filename characters (e.g. .txt, .log)
  2. Compute directory placement via --tmpdir instead of encoding it in the suffix
  3. Sanitize dynamic suffixes: `suffix=$(basename "$candidate")` before use
  4. If a nested name is needed, create the directory and pass it as --tmpdir

Example fix

// before
mktemp --suffix="sub/x.log" XXXXXX
// after
mktemp --tmpdir="./sub" --suffix=.log XXXXXX
Defensive patterns

Strategy: validation

Validate before calling

if (suffix.includes('/')) {
  throw new RangeError(`invalid suffix '${suffix}': must not contain '/'`);
}

Type guard

const isPlainSuffix = (s: string): boolean => !s.includes('/') && s.length > 0;

Try / catch

try {
  await Bun.$`mktemp --suffix=${suffix} ${tmpl}`.quiet();
} catch (e) {
  if (String(e).includes('invalid suffix')) {
    const clean = path.basename(suffix); // strip any path shape
    await Bun.$`mktemp --suffix=${clean} ${tmpl}`.quiet();
  } else throw e;
}

Prevention

When it happens

Trigger: `mktemp --suffix=dir/.tmp XXXXXX` or --suffix built from a path variable containing '/'; shell expansion injecting a path fragment into the suffix.

Common situations: Dynamically composed suffixes like `--suffix=".$(basename $0).tmp"` where basename unexpectedly returns a path; copy-pasted suffixes including directories; cross-platform scripts with path-shaped suffixes.

Related errors


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