{"record":{"id":"6ccf97879c3877d3","repo":"apache/hadoop","slug":"no-version-in-key-path-versionname","errorCode":null,"errorMessage":"No version in key path ${versionName}","messagePattern":"No version in key path (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/KeyProvider.java","lineNumber":647,"sourceCode":"\n  /**\n   * Ensures that any changes to the keys are written to persistent store.\n   * @throws IOException raised on errors performing I/O.\n   */\n  public abstract void flush() throws IOException;\n\n  /**\n   * Split the versionName in to a base name. Converts \"/aaa/bbb@3\" to\n   * \"/aaa/bbb\".\n   * @param versionName the version name to split\n   * @return the base name of the key\n   * @throws IOException raised on errors performing I/O.\n   */\n  public static String getBaseName(String versionName) throws IOException {\n    Objects.requireNonNull(versionName, \"VersionName cannot be null\");\n    int div = versionName.lastIndexOf('@');\n    if (div == -1) {\n      throw new IOException(\"No version in key path \" + versionName);\n    }\n    return versionName.substring(0, div);\n  }\n\n  /**\n   * Build a version string from a basename and version number. Converts\n   * \"/aaa/bbb\" and 3 to \"/aaa/bbb@3\".\n   * @param name the basename of the key\n   * @param version the version of the key\n   * @return the versionName of the key.\n   */\n  protected static String buildVersionName(String name, int version) {\n    return name + \"@\" + version;\n  }\n\n  /**\n   * Find the provider with the given key.\n   *","sourceCodeStart":629,"sourceCodeEnd":665,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/KeyProvider.java#L629-L665","documentation":"getBaseName splits a version name such as '/aaa/bbb@3' into '/aaa/bbb' by cutting at the last '@'. If the string contains no '@' there is no version component to strip, so the method throws IOException rather than returning the input unchanged. A null input is rejected earlier with Objects.requireNonNull(\"VersionName cannot be null\").","triggerScenarios":"Passing a base key name ('/aaa/bbb') where a version name ('/aaa/bbb@0') is required; names assembled by string concatenation that dropped the '@version' suffix; parsing key names from external sources where the version tag was trimmed.","commonSituations":"Clients threading key base names into APIs that expect KeyVersion.getVersionName() values; log/config parsing that strips '@' segments as comments.","solutions":["Pass values obtained from KeyVersion.getVersionName() or buildVersionName(name, version)","If the input may be a base name, check versionName.lastIndexOf('@') != -1 first and skip the split","When constructing version names manually, always append '@' + version"],"exampleFix":"// before\nString base = KeyProvider.getBaseName(\"/aaa/bbb\"); // throws: no '@'\n\n// after\nString in = \"/aaa/bbb\";\nint at = in.lastIndexOf('@');\nString base = (at == -1) ? in : in.substring(0, at);","handlingStrategy":"type-guard","validationCode":"static boolean isVersionName(String s) {\n  return s != null && s.lastIndexOf('@') != -1;\n}","typeGuard":"static String baseNameOrSelf(String s) throws IOException {\n  Objects.requireNonNull(s, \"VersionName cannot be null\");\n  int at = s.lastIndexOf('@');\n  return (at == -1) ? s : s.substring(0, at);\n}","tryCatchPattern":"try { base = KeyProvider.getBaseName(versionName); } catch (IOException e) { if (String.valueOf(e.getMessage()).startsWith(\"No version in key path\")) { base = versionName; /* input was already a base name */ } else { throw e; } }","preventionTips":["Only feed getBaseName values that came from getVersionName()/buildVersionName()","Keep base names and version names in distinct variables/types","When parsing external names, check for '@' before splitting"],"tags":["java","hadoop","key-provider","parsing","key-name"],"backgroundTag":"key-version-name-parse","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}