spring-projects/spring-ai · error · IOException
Invalid filename for file '':
Error message
Invalid filename for file '':
What it means
resolveSafeChildPath converts the raw filename with Path.of(); if the name is not a valid path on the current filesystem (e.g. contains NUL bytes, illegal characters on Windows, or platform-invalid sequences) Path.of throws InvalidPathException, which is rethrown as an IOException. Because filenames come from model-influenced API metadata, they are treated as untrusted and validated strictly.
Source
Thrown at models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/AnthropicSkillsResponseHelper.java:158
}
/**
* Validate an API-provided filename and resolve it to a child of {@code targetDir}.
* Rejects null/blank names, absolute paths, names containing path separators or
* {@code .}/{@code ..} segments, and names that resolve outside {@code targetDir}.
* Filenames come from model-influenced API metadata and must not be trusted as safe
* path components.
*/
static Path resolveSafeChildPath(Path targetDir, @Nullable String rawName, String fileId) throws IOException {
if (rawName == null || rawName.isBlank()) {
throw new IOException("Invalid filename for file '" + fileId + "': null or blank");
}
Path name;
try {
name = Path.of(rawName);
}
catch (InvalidPathException ex) {
throw new IOException("Invalid filename for file '" + fileId + "': " + rawName, ex);
}
if (name.isAbsolute() || name.getRoot() != null) {
throw new IOException("Invalid filename for file '" + fileId + "': absolute path '" + rawName + "'");
}
if (name.getNameCount() != 1) {
throw new IOException(
"Invalid filename for file '" + fileId + "': must be a single path segment '" + rawName + "'");
}
String only = name.getName(0).toString();
if (only.equals(".") || only.equals("..")) {
throw new IOException("Invalid filename for file '" + fileId + "': '" + rawName + "'");
}
// One extra hardening check to make sure nothing fell through the cracks above
// (future tweaks to the rules, odd platform path quirks, etc.).
Path base = targetDir.toAbsolutePath().normalize();
Path resolved = base.resolve(only).normalize();
if (!resolved.startsWith(base)) {View on GitHub (pinned to 98a7beda4f)
Solutions
- Sanitize the filename before calling resolveSafeChildPath: strip or replace illegal characters with a safe substitute (e.g. '_').
- Skip the offending file entry and log the fileId and raw name for investigation.
- Generate your own deterministic safe filename (e.g. fileId + detected extension) instead of trusting the API name.
- If targeting multiple OSes, test filename handling on Windows where the illegal-character set is larger.
Example fix
// before
Path p = resolveSafeChildPath(targetDir, rawNameFromApi, fileId);
// after
String safe = rawNameFromApi.replaceAll("[\\u0000:*?\"<>|]", "_");
Path p = resolveSafeChildPath(targetDir, safe, fileId); Defensive patterns
Strategy: try-catch
Validate before calling
try { Path.of(rawName); } catch (InvalidPathException e) {
log.warn("Filename not valid on this filesystem for file {}: {}", fileId, rawName);
return;
} Type guard
static boolean isConstructablePath(String rawName) {
try { Path.of(rawName); return true; } catch (InvalidPathException e) { return false; }
} Try / catch
try {
Path p = AnthropicSkillsResponseHelper.resolveSafeChildPath(targetDir, rawName, fileId);
} catch (IOException e) {
if (e.getCause() instanceof InvalidPathException) {
log.warn("Skipping file {} with OS-invalid name '{}'", fileId, rawName);
} else throw e;
} Prevention
- Sanitize model/API-supplied filenames (replace illegal chars) before path resolution.
- Test on Windows, whose illegal-character set is larger than Linux's.
- Prefer deriving filenames from fileId rather than trusting model-generated names.
When it happens
Trigger: A file entry whose name contains characters illegal for the OS filesystem — NUL (\0), on Windows characters like : * ? " < > | or reserved names (CON, NUL), or invalid UTF-8-derived sequences — passed into resolveSafeChildPath.
Common situations: Model-generated filenames containing special characters; Windows hosts receiving names with colons or wildcards; responses from a different OS convention (Unix-style names with characters Windows rejects); corrupted/malicious API payloads.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- Invalid filename for file '': null or blank
- Maximum of 8 skills per request. Provided:
- Invalid filename for file '': absolute path ''
- Unsupported media type: . Supported types are: images (image
- Unsupported media data type: . Expected byte[] or String.
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/ad0e2d29da6d13fd.
Report an issue: GitHub.