{"record":{"id":"dc3213b6d5e56e16","repo":"apache/beam","slug":"azure-credentials-provider-could-not-be-read","errorCode":null,"errorMessage":"Azure credentials provider could not be read.","messagePattern":"Azure credentials provider could not be read\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/azure/src/main/java/org/apache/beam/sdk/io/azure/options/AzureModule.java","lineNumber":100,"sourceCode":"  @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)\n  private static class TokenCredentialMixin {}\n\n  private static class TokenCredentialDeserializer extends JsonDeserializer<TokenCredential> {\n\n    @Override\n    public TokenCredential deserialize(JsonParser jsonParser, DeserializationContext context)\n        throws IOException {\n      return context.readValue(jsonParser, TokenCredential.class);\n    }\n\n    @Override\n    public TokenCredential deserializeWithType(\n        JsonParser jsonParser, DeserializationContext context, TypeDeserializer typeDeserializer)\n        throws IOException {\n      Map<String, String> asMap =\n          jsonParser.readValueAs(new TypeReference<Map<String, String>>() {});\n      if (asMap == null) {\n        throw new IOException(\"Azure credentials provider could not be read.\");\n      }\n\n      String typeNameKey = typeDeserializer.getPropertyName();\n      String typeName = asMap.get(typeNameKey);\n      if (typeName == null) {\n        throw new IOException(\n            String.format(\"Azure credentials provider type name key '%s' not found\", typeNameKey));\n      }\n\n      if (typeName.equals(DefaultAzureCredential.class.getSimpleName())) {\n        return new DefaultAzureCredentialBuilder().build();\n      } else if (typeName.equals(ClientSecretCredential.class.getSimpleName())) {\n        return new ClientSecretCredentialBuilder()\n            .clientId(asMap.getOrDefault(AZURE_CLIENT_ID, \"\"))\n            .clientSecret(asMap.getOrDefault(AZURE_CLIENT_SECRET, \"\"))\n            .tenantId(asMap.getOrDefault(AZURE_TENANT_ID, \"\"))\n            .build();\n      } else if (typeName.equals(ManagedIdentityCredential.class.getSimpleName())) {","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/azure/src/main/java/org/apache/beam/sdk/io/azure/options/AzureModule.java#L82-L118","documentation":"AzureModule's TokenCredentialDeserializer.deserializeWithType reads the serialized credential as a Map<String,String>; if the JSON parses to null, it throws IOException \"Azure credentials provider could not be read.\". This guards the custom Jackson (de)serialization of Azure TokenCredential objects stored in Beam pipeline options.","triggerScenarios":"Deserializing pipeline options whose TokenCredential field contains JSON 'null' or an empty/absent value that readValueAs resolves to null; corrupt or hand-edited option payloads missing the credential object.","commonSituations":"Restoring a saved pipeline/template where the credential field was stripped or null; passing AzureOptions with an unset credential through template-based launches; JSON payloads produced by an older serializer version.","solutions":["Ensure a TokenCredential is actually set on AzureOptions (azureOptions.setCredential(...)) before serialization.","Inspect the serialized JSON and confirm the credential field is a non-null object with a type-name key.","Use DefaultAzureCredential when no explicit credential is needed, so a valid object is always serialized.","Validate pipeline options before launching (e.g. asMap of AzureOptions) to catch null credentials early."],"exampleFix":"// before\nAzureOptions options = ...; // credential never set -> serialized null\n// after\noptions.setCredential(new DefaultAzureCredentialBuilder().build());","handlingStrategy":"validation","validationCode":"if (azureOptions.getCredential() == null) {\n  throw new IllegalStateException(\"AzureOptions.credential must be set before serialization\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  return mapper.readValue(json, TokenCredential.class);\n} catch (IOException e) {\n  if (e.getMessage().contains(\"could not be read\")) {\n    throw new IllegalStateException(\"credential payload is null/empty; re-set AzureOptions.credential\", e);\n  }\n  throw e;\n}","preventionTips":["Always set a TokenCredential on AzureOptions before exporting templates","Never hand-edit serialized credential JSON","Validate pipeline options programmatically before launch","Prefer DefaultAzureCredential so a valid object is always present"],"tags":["java","jackson","deserialization","azure-credentials"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}