kestra-io/kestra · error · IOException

Output file '%s' contains unsupported characters. Allowed: l

Error message

Output file '%s' contains unsupported characters. Allowed: letters, digits, hyphens, dots, underscores, plus, tilde, hash, equals, slashes, commas, colons, semicolons.

What it means

Thrown by ScriptService.validateStoragePath() when an output file's relative path does not match VALID_STORAGE_PATH_PATTERN. The pattern restricts filenames to letters, digits, hyphens, dots, underscores, plus, tilde, hash, equals, slashes, commas, colons, and semicolons. Any other character (spaces, parentheses, Unicode, etc.) is rejected because internal storage keys must be URL-safe. This fires during uploadOutputFiles() before the file is persisted to object storage.

Source

Thrown at core/src/main/java/io/kestra/core/models/tasks/runners/ScriptService.java:155

                .filter(path -> !path.startsWith("."))
                .forEach(throwConsumer(path ->
                {
                    String filename = outputDir.relativize(path).toString();
                    validateStoragePath(filename);

                    uploaded.put(
                        filename,
                        runContext.storage().putFile(path.toFile(), filename)
                    );
                }));
        }

        return uploaded;
    }

    static void validateStoragePath(String filename) throws IOException {
        if (!VALID_STORAGE_PATH_PATTERN.matcher(filename).matches()) {
            throw new IOException(
                "Output file '%s' contains unsupported characters. Allowed: letters, digits, hyphens, dots, underscores, plus, tilde, hash, equals, slashes, commas, colons, semicolons."
                    .formatted(filename)
            );
        }
    }

    public static List<String> scriptCommands(List<String> interpreter, List<String> beforeCommands, String command) {
        return scriptCommands(interpreter, beforeCommands, List.of(command), TargetOS.LINUX);
    }

    public static List<String> scriptCommands(List<String> interpreter, List<String> beforeCommands, List<String> commands) {
        return scriptCommands(interpreter, beforeCommands, commands, TargetOS.LINUX);
    }

    public static List<String> scriptCommands(List<String> interpreter, List<String> beforeCommands, String command, TargetOS targetOS) {
        return scriptCommands(interpreter, beforeCommands, List.of(command), targetOS);
    }

View on GitHub (pinned to 823fada927)

Solutions

  1. Sanitize output filenames to use only the allowed character set before writing.
  2. Replace spaces with underscores or hyphens.
  3. If Unicode is required, transliterate to ASCII or encode the name.

Example fix

# before
script writes: 'result (1).csv'
# IOException: unsupported characters

# after
script writes: 'result_1.csv'
Defensive patterns

Strategy: validation

Validate before calling

// VALID_STORAGE_PATH_PATTERN must allow only: [A-Za-z0-9.\-_+~#=/,;:]
private static final Pattern ALLOWED = Pattern.compile("[A-Za-z0-9.\\-_+~#=/,;:]+");
if (!ALLOWED.matcher(filename).matches()) {
    throw new IOException("Output file contains unsupported characters: " + filename);
}

Type guard

const ALLOWED = /^[A-Za-z0-9.\-_+~#=/,;:]+$/;
function isSafeStorageName(name: string): boolean { return ALLOWED.test(name); }

Try / catch

try {
    ScriptService.uploadOutputFiles(runContext, outputDir);
} catch (IOException e) {
    log.error("Output filename rejected: {}", e.getMessage());
}

Prevention

When it happens

Trigger: An output file's name contains a space, parenthesis, exclamation mark, or any non-ASCII character; a script writes a file like 'result (1).csv' or 'café.txt'; a generated filename includes an ampersand or question mark.

Common situations: User-named output files with spaces or special characters; localized filenames; shell redirection producing unexpected names.

Related errors


AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14). Data as JSON: /api/errors/bd8601d9d07883a4. Report an issue: GitHub.