{"record":{"id":"a1c3070845efb897","repo":"didi/DoKit","slug":"transformation-key-must-not-be-null","errorCode":null,"errorMessage":"Transformation key must not be null.","messagePattern":"Transformation key must not be null\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/Request.java","lineNumber":430,"sourceCode":"      }\n      if (this.priority != null) {\n        throw new IllegalStateException(\"Priority already set.\");\n      }\n      this.priority = priority;\n      return this;\n    }\n\n    /**\n     * Add a custom transformation to be applied to the image.\n     * <p>\n     * Custom transformations will always be run after the built-in transformations.\n     */\n    public Builder transform(com.didichuxing.doraemonkit.picasso.Transformation transformation) {\n      if (transformation == null) {\n        throw new IllegalArgumentException(\"Transformation must not be null.\");\n      }\n      if (transformation.key() == null) {\n        throw new IllegalArgumentException(\"Transformation key must not be null.\");\n      }\n      if (transformations == null) {\n        transformations = new ArrayList<com.didichuxing.doraemonkit.picasso.Transformation>(2);\n      }\n      transformations.add(transformation);\n      return this;\n    }\n\n    /**\n     * Add a list of custom transformations to be applied to the image.\n     * <p>\n     * Custom transformations will always be run after the built-in transformations.\n     */\n    public Builder transform(List<? extends Transformation> transformations) {\n      if (transformations == null) {\n        throw new IllegalArgumentException(\"Transformation list must not be null.\");\n      }\n      for (int i = 0, size = transformations.size(); i < size; i++) {","sourceCodeStart":412,"sourceCodeEnd":448,"githubUrl":"https://github.com/didi/DoKit/blob/626827cddb2feb2f3aee87a52a064b4e5ca2bed4/Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/Request.java#L412-L448","documentation":"Thrown by Request.Builder.transform(Transformation) when the transformation object is non-null but its key() method returns null. The key string identifies the transformation in Picasso's cache keys; a null key makes cached results unaddressable, so it is rejected.","triggerScenarios":"Passing a custom Transformation whose key() returns null (e.g., string concatenation that yielded null, or a stub implementation).","commonSituations":"Writing a custom Transformation and leaving key() unimplemented or returning a null field; key() built from a nullable config field; copied skeleton code with 'return null;' left in.","solutions":["Implement key() to return a stable non-null string describing the transformation (e.g., \"circle()\" or \"rounded(radius=8)\").","Include parameters in the key so different configurations produce different cache entries.","Add a unit test asserting key() != null for every custom Transformation."],"exampleFix":"// before\nclass CircleTransform implements Transformation {\n  public String key() { return null; }\n  ...\n}\n\n// after\nclass CircleTransform implements Transformation {\n  public String key() { return \"circle()\"; }\n  ...\n}","handlingStrategy":"validation","validationCode":"if (transformation != null && transformation.key() != null) { builder.transform(transformation); }","typeGuard":"static boolean hasValidKey(Transformation t) {\n  return t != null && t.key() != null && !t.key().isEmpty();\n}","tryCatchPattern":null,"preventionTips":["Always implement key() with a literal, parameter-encoding string.","Unit-test key() of every custom Transformation for non-null."],"tags":["android","picasso","image-transform","caching","null-safety"],"backgroundTag":null,"analyzedSha":"626827cddb2feb2f3aee87a52a064b4e5ca2bed4","analyzedAt":"2026-08-14T12:45:58.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}