{"record":{"id":"b49646c8db52c48a","repo":"apache/druid","slug":"invalid-path-s-should-contain","errorCode":null,"errorMessage":"Invalid path: [%s], should contain '/'","messagePattern":"Invalid path: \\[(.+?)\\], should contain '/'","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/loading/DataSegmentKiller.java","lineNumber":46,"sourceCode":"import java.util.List;\n\n/**\n * DataSegmentKiller knows how to kill segments from the Druid system.\n * Since any implementation of DataSegmentKiller is initialized when an ingestion job starts\n * if a deep storage extension is loaded even when that deep storage is actually not used,\n * implementations should avoid initializing the deep storage client immediately\n * but defer it until the deep storage client is actually used.\n */\n@ExtensionPoint\npublic interface DataSegmentKiller\n{\n  Logger log = new Logger(DataSegmentKiller.class);\n\n  static String descriptorPath(String path)\n  {\n    int lastPathSeparatorIndex = path.lastIndexOf('/');\n    if (lastPathSeparatorIndex == -1) {\n      throw new IAE(\"Invalid path: [%s], should contain '/'\", path);\n    }\n    return path.substring(0, lastPathSeparatorIndex) + \"/descriptor.json\";\n  }\n\n  /**\n   * Removes segment files (index and metadata) from deep storage.\n   * @param segment the segment to kill\n   * @throws SegmentLoadingException if the segment could not be completely removed\n   */\n  void kill(DataSegment segment) throws SegmentLoadingException;\n\n  /**\n   * Kills a list of segments from deep storage. The default implementation calls kill on the segments in a loop.\n   * Implementers of this interface can leverage batch / bulk deletes to be more efficient. It is preferable to attempt\n   * to delete all segments even if there is an issue with deleting a single one. This is up to implementers to\n   * implement as putting a try catch around the default kill via iteration can be problematic if the client of the deep\n   * storage is unable to authenticate itself and segment loading exception doesn't encode enough information in it to \\\n   * understand why it failed.","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/loading/DataSegmentKiller.java#L28-L64","documentation":"DataSegmentKiller.descriptorPath derives the descriptor.json location from a segment's storage path by replacing the last path component. If the path contains no '/' separator at all it cannot locate a parent directory, so it throws IAE indicating the path is invalid for descriptor lookup.","triggerScenarios":"Calling DataSegmentKiller APIs (or descriptorPath directly) with a segment storage path lacking any '/', e.g. a bare filename or a misconfigured single-component deep storage key.","commonSituations":"Custom LoadSpec/UriExtractionStrategy producing paths without separators; hand-editing segment metadata paths; deep storage emulators that flatten keys.","solutions":["Ensure the segment path stored in the metadata store is a full deep-storage path with '/' separators","Fix the LoadSpec or storage key construction that produced the separator-less path","Re-upload or repair the segment entry in the segments table with a correct path"],"exampleFix":"// before\nString path = \"index.zip\"; // no separator\nString desc = DataSegmentKiller.descriptorPath(path); // throws\n// after\nString path = \"s3://bucket/druid/segments/ds/2020-01-01/seg/index.zip\";\nString desc = DataSegmentKiller.descriptorPath(path); // .../seg/descriptor.json","handlingStrategy":"validation","validationCode":"if (path == null || !path.contains(\"/\")) throw new IllegalArgumentException(\"Segment path must be a full deep-storage path: \" + path);","typeGuard":"boolean isDeepStoragePath(String p) { return p != null && p.lastIndexOf('/') > 0; }","tryCatchPattern":"try { String desc = DataSegmentKiller.descriptorPath(path); } catch (IAE e) { log.error(\"Bad segment path in metadata: %s\", path); throw e; }","preventionTips":["Never hand-edit paths in the segments metadata table","Validate LoadSpec/storage key formats when writing custom deep storage modules","Run metadata health checks that assert path shape before cleanup jobs"],"tags":["deep-storage","path","illegal-argument"],"backgroundTag":"invalid-argument-format","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}