{"record":{"id":"70a4a2eba8664175","repo":"pentaho/pentaho-kettle","slug":"failed-to-fetch-driver-metadata-for-driverid-http-status","errorCode":null,"errorMessage":"Failed to fetch driver metadata for '{driverId}' — HTTP {status} from {metadataUrl}","messagePattern":"Failed to fetch driver metadata for '(.+?)' — HTTP (.+?) from (.+?)","errorType":"exception","errorClass":"KettleDatabaseException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/database/Database.java","lineNumber":752,"sourceCode":"          + \"Set the environment variable or system property 'JDBC_DRIVER_SERVICE_URL'.\" );\n    }\n\n    String metadataUrl = serviceBaseUrl + \"/api/v1/connection-drivers/\" + driverId;\n    HttpURLConnection conn = null;\n    try {\n      conn = (HttpURLConnection) new URL( metadataUrl ).openConnection();\n      conn.setConnectTimeout( 10_000 );\n      conn.setReadTimeout( 60_000 );\n      conn.setRequestMethod( \"GET\" );\n\n      String bearerToken = CmsTokenProvider.getInstance().getToken();\n      if ( bearerToken != null ) {\n        conn.setRequestProperty( \"Authorization\", \"Bearer \" + bearerToken );\n      }\n\n      int status = conn.getResponseCode();\n      if ( status != HttpURLConnection.HTTP_OK ) {\n        throw new KettleDatabaseException(\n          \"Failed to fetch driver metadata for '\" + driverId + \"' — HTTP \" + status + \" from \" + metadataUrl );\n      }\n\n      try ( java.io.InputStream is = conn.getInputStream() ) {\n        return new ObjectMapper().readValue( is, Map.class );\n      }\n    } catch ( KettleDatabaseException e ) {\n      throw e;\n    } catch ( Exception e ) {\n      throw new KettleDatabaseException(\n        \"Failed to fetch driver metadata for '\" + driverId + \"' from '\" + metadataUrl + \"': \" + e.getMessage(), e );\n    } finally {\n      if ( conn != null ) {\n        conn.disconnect();\n      }\n    }\n  }\n","sourceCodeStart":734,"sourceCodeEnd":770,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/database/Database.java#L734-L770","documentation":"The driver-metadata HTTP service responded with a non-200 status. getMetadataFromDriver treats anything other than HTTP 200 as a hard failure and includes the driverId, status code, and requested URL in the message. It wraps problems like 404 (unknown driver), 401/403 (bad bearer token), and 5xx (service down).","triggerScenarios":"driverMetadata -> getMetadataFromDriver issues GET {base}/api/v1/connection-drivers/{driverId} and the server returns e.g. 404, 401, 403, 500, or 503 instead of 200.","commonSituations":"Typo'd driverId; metadata service does not know the driver version; expired or missing bearer token (Authorization header rejected); metadata service partially deployed and returning 5xx; a proxy stripping the path.","solutions":["Check the status code in the message: 404 => fix driverId or deploy the driver definition; 401/403 => fix the bearer token; 5xx => check service health","Verify JDBC_DRIVER_SERVICE_URL points at the correct service root (no missing path prefix, no trailing duplication)","Confirm the driverId exists by calling the same REST endpoint manually (curl) with the same auth header","Retry if the status is 503/transient and the service is restarting"],"exampleFix":"// before\nDatabase.driverMetadata(\"mysql8x\"); // 404: driver not published\n// after\nDatabase.driverMetadata(\"MySQL\"); // id that the service actually exposes\n// or fix token:\nconn.setRequestProperty(\"Authorization\", \"Bearer \" + validToken);","handlingStrategy":"try-catch","validationCode":"HttpURLConnection probe = (HttpURLConnection) new URL(baseUrl + \"/api/v1/connection-drivers/health\").openConnection();\nif (probe.getResponseCode() != 200) throw new IllegalStateException(\"Driver metadata service unhealthy: \" + probe.getResponseCode());","typeGuard":null,"tryCatchPattern":"try { map = db.driverMetadata(driverId); } catch (KettleDatabaseException e) { if (e.getMessage().matches(\".*HTTP \\\\d+.*\")) { int status = parseStatus(e.getMessage()); if (status >= 500 || status == 429) retryWithBackoff(); else log.error(\"Permanent failure for driverId, status \" + status); } else throw e; }","preventionTips":["Curl the exact metadata endpoint with the same auth header before deploying","Keep the bearer token fresh and scoped correctly","Confirm driverIds against the service's published list","Monitor the metadata service for 5xx rates"],"tags":["http","rest","jdbc","metadata","network"],"backgroundTag":"http-error-response","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}