{"record":{"id":"ef0d592d0c4f9af4","repo":"apache/iceberg","slug":"path-s-does-not-start-with-s","errorCode":null,"errorMessage":"Path %s does not start with %s","messagePattern":"Path (.+?) does not start with (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/RewriteTablePathUtil.java","lineNumber":935,"sourceCode":"   * Compute the relative path from a prefix to a given path.\n   *\n   * <p>If the path is under the prefix, returns the portion after the prefix. If the path equals\n   * the prefix (representing the root directory itself), returns an empty string.\n   *\n   * <p>Trailing separators are normalized: \"/a\" and \"/a/\" are treated as equivalent for both path\n   * and prefix. This allows flexibility when paths come from different sources that may or may not\n   * include trailing separators.\n   *\n   * @param path absolute path to relativize\n   * @param prefix prefix path to remove\n   * @return relative path from prefix to path, or empty string if path equals prefix\n   * @throws IllegalArgumentException if path is not under or equal to prefix\n   */\n  public static String relativize(String path, String prefix) {\n    String toRemove = maybeAppendFileSeparator(prefix);\n    String normalizedPath = maybeAppendFileSeparator(path);\n    if (!normalizedPath.startsWith(toRemove)) {\n      throw new IllegalArgumentException(\n          String.format(\"Path %s does not start with %s\", normalizedPath, toRemove));\n    }\n    return normalizedPath.equals(toRemove) ? \"\" : path.substring(toRemove.length());\n  }\n\n  public static String maybeAppendFileSeparator(String path) {\n    return path.endsWith(FILE_SEPARATOR) ? path : path + FILE_SEPARATOR;\n  }\n\n  /**\n   * Construct a staging path under a given staging directory, preserving relative directory\n   * structure to avoid conflicts when multiple files have the same name but different paths.\n   *\n   * @param originalPath source path\n   * @param sourcePrefix source prefix to be replaced\n   * @param stagingDir staging directory\n   * @return a staging path under the staging directory that preserves the relative path structure\n   */","sourceCodeStart":917,"sourceCodeEnd":953,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/RewriteTablePathUtil.java#L917-L953","documentation":"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.","triggerScenarios":"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.","commonSituations":"Wrong or truncated sourcePrefix; files written by a previous table location; case-sensitive mismatch or missing trailing slash handled inconsistently.","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."],"exampleFix":"// before\nString rel = RewriteTablePathUtil.relativize(path, \"s3://bucket/db\"); // path is s3://bucket/warehouse/db/table/f.parquet\n// after\nString rel = RewriteTablePathUtil.relativize(path, \"s3://bucket/warehouse/db/table\");","handlingStrategy":"validation","validationCode":"String rel = RewriteTablePathUtil.relativize(path, prefix); // pre-check:\nif (!path.startsWith(prefix)) throw new IllegalArgumentException(\"path not under prefix: \" + path);","typeGuard":"boolean relativizable(String path, String prefix) { String p = RewriteTablePathUtil.maybeAppendFileSeparator(path); String r = RewriteTablePathUtil.maybeAppendFileSeparator(prefix); return p.startsWith(r); }","tryCatchPattern":"try { rel = RewriteTablePathUtil.relativize(path, prefix); } catch (IllegalArgumentException e) { /* fix prefix argument */ }","preventionTips":["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"],"tags":["iceberg","rewrite-table-path","prefix-mismatch"],"backgroundTag":"invalid-argument-value","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}