apache/iceberg · error · IllegalArgumentException
Path does not start with
Error message
Path %s does not start with %s
What it means
Thrown by RewriteTablePathUtil.relativize when a path does not start with the given prefix (after appending file separators). Relativize strips the prefix to produce the relative path used under the target location; a path outside the prefix cannot be relativized.
Solutions
- Pass the full, exact source location as prefix so every file path starts with it.
- Compare the offending path in the message with the prefix and fix the prefix argument.
- Rewrite or relocate files stored outside the table's current location before calling the utility.
Example fix
// before String rel = RewriteTablePathUtil.relativize(path, "s3://bucket/db"); // path is s3://bucket/warehouse/db/table/f.parquet // after String rel = RewriteTablePathUtil.relativize(path, "s3://bucket/warehouse/db/table");
Defensive patterns
Strategy: validation
Validate before calling
String rel = RewriteTablePathUtil.relativize(path, prefix); // pre-check:
if (!path.startsWith(prefix)) throw new IllegalArgumentException("path not under prefix: " + path); Type guard
boolean relativizable(String path, String prefix) { String p = RewriteTablePathUtil.maybeAppendFileSeparator(path); String r = RewriteTablePathUtil.maybeAppendFileSeparator(prefix); return p.startsWith(r); } Try / catch
try { rel = RewriteTablePathUtil.relativize(path, prefix); } catch (IllegalArgumentException e) { /* fix prefix argument */ } Prevention
- Use the full table location as prefix, no truncation
- Let the utility append the trailing separator — don't double-handle slashes
- Validate all file locations against the prefix in a dry run
When it happens
Trigger: Any RewriteTablePathUtil newPath/relativePath call where path is not under or equal to prefix — e.g. manifest, manifest-list, or data file locations not under the supplied table prefix.
Common situations: Wrong or truncated sourcePrefix; files written by a previous table location; case-sensitive mismatch or missing trailing slash handled inconsistently.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Expected delete file
- Expected delete file to be under the source prefix: but…
- ALTER VIEW AS is not supported. Use CREATE OR REPLACE VIEW…
- apply(value) is deprecated, use bind(Type).apply(value)
- apply(value) is deprecated, use bind(Type).apply(value)
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/ef0d592d0c4f9af4.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/RewriteTablePathUtil.java:935
* Compute the relative path from a prefix to a given path.
*
* <p>If the path is under the prefix, returns the portion after the prefix. If the path equals
* the prefix (representing the root directory itself), returns an empty string.
*
* <p>Trailing separators are normalized: "/a" and "/a/" are treated as equivalent for both path
* and prefix. This allows flexibility when paths come from different sources that may or may not
* include trailing separators.
*
* @param path absolute path to relativize
* @param prefix prefix path to remove
* @return relative path from prefix to path, or empty string if path equals prefix
* @throws IllegalArgumentException if path is not under or equal to prefix
*/
public static String relativize(String path, String prefix) {
String toRemove = maybeAppendFileSeparator(prefix);
String normalizedPath = maybeAppendFileSeparator(path);
if (!normalizedPath.startsWith(toRemove)) {
throw new IllegalArgumentException(
String.format("Path %s does not start with %s", normalizedPath, toRemove));
}
return normalizedPath.equals(toRemove) ? "" : path.substring(toRemove.length());
}
public static String maybeAppendFileSeparator(String path) {
return path.endsWith(FILE_SEPARATOR) ? path : path + FILE_SEPARATOR;
}
/**
* Construct a staging path under a given staging directory, preserving relative directory
* structure to avoid conflicts when multiple files have the same name but different paths.
*
* @param originalPath source path
* @param sourcePrefix source prefix to be replaced
* @param stagingDir staging directory
* @return a staging path under the staging directory that preserves the relative path structure
*/View on GitHub (pinned to 86d9c8fc54)