{"record":{"id":"63d0f69ebb8aeeab","repo":"apache/seatunnel","slug":"describe-object-failed","errorCode":"DESCRIBE_OBJECT_FAILED","errorMessage":"HTTP \" + status + \" describing \" + objectName + \": \" + body","messagePattern":"HTTP \" \\+ status \\+ \" describing \" \\+ objectName \\+ \": \" \\+ body","errorType":"error_code","errorClass":"SalesforceConnectorException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-salesforce/src/main/java/org/apache/seatunnel/connectors/seatunnel/salesforce/client/SalesforceClient.java","lineNumber":137,"sourceCode":"        } catch (SalesforceConnectorException e) {\n            throw e;\n        } catch (Exception e) {\n            throw new SalesforceConnectorException(SalesforceConnectorErrorCode.AUTH_FAILED, e);\n        }\n    }\n\n    public CatalogTable describeObject(String database, String objectName) {\n        String url =\n                authorizedInstanceUrl\n                        + String.format(DESCRIBE_PATH, params.getApiVersion(), objectName);\n        HttpGet get = new HttpGet(url);\n        get.setHeader(HttpHeaders.AUTHORIZATION, \"Bearer \" + accessToken);\n\n        try (CloseableHttpResponse response = httpClient.execute(get)) {\n            int status = response.getStatusLine().getStatusCode();\n            String body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);\n            if (status != 200) {\n                throw new SalesforceConnectorException(\n                        SalesforceConnectorErrorCode.DESCRIBE_OBJECT_FAILED,\n                        \"HTTP \" + status + \" describing \" + objectName + \": \" + body);\n            }\n            return buildCatalogTable(database, objectName, objectMapper.readTree(body));\n        } catch (SalesforceConnectorException e) {\n            throw e;\n        } catch (Exception e) {\n            throw new SalesforceConnectorException(\n                    SalesforceConnectorErrorCode.DESCRIBE_OBJECT_FAILED, e);\n        }\n    }\n\n    private CatalogTable buildCatalogTable(String database, String objectName, JsonNode describe) {\n        TableSchema.Builder schemaBuilder = TableSchema.builder();\n        for (JsonNode field : describe.get(\"fields\")) {\n            String name = field.get(\"name\").asText();\n            String sfType = field.get(\"type\").asText();\n            SeaTunnelDataType<?> seaType = mapSalesforceType(sfType);","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-salesforce/src/main/java/org/apache/seatunnel/connectors/seatunnel/salesforce/client/SalesforceClient.java#L119-L155","documentation":"Thrown by SalesforceClient.describeObject when the Salesforce REST API /sobjects/{object}/describe call returns a non-200 status. The message embeds the HTTP status, the object name, and the raw response body so the actual Salesforce cause (auth failure, missing object, etc.) is visible. It wraps any failure of the describe request into the connector's DESCRIBE_OBJECT_FAILED error code.","triggerScenarios":"Calling describeObject for an object name that does not exist (400/404), an expired or invalid access token (401/403), or any Salesforce-side error during the GET describe request.","commonSituations":"Typo in the table_path object name in tables_configs; insufficient API access on the connected app; Salesforce org returned INVALID_SESSION_ID because the access token expired between login and describe; the object is not queryable for the integration user.","solutions":["Read the embedded HTTP status and body in the message to identify the Salesforce cause","Verify the object name in table_path matches a real Salesforce object (case-insensitive API name, e.g. Account)","Re-authenticate: check the token endpoint / credentials so the Bearer token is valid at request time","Grant the integration user API access and View permission on the object in the Salesforce profile/permission set"],"exampleFix":"// before\ntable_path = \"default.Accouts\"  // typo\n// after\ntable_path = \"default.Accounts\"","handlingStrategy":"try-catch","validationCode":"// validate object exists before connecting\n// curl -H \"Authorization: Bearer $TOKEN\" \\\n//   https://<instance>/services/data/vXX.0/sobjects/Account/describe\n// expect HTTP 200 before running the job","typeGuard":"boolean isObjectNameValid(String name) {\n    return name != null && name.matches(\"[A-Za-z][A-Za-z0-9_]*\");\n}","tryCatchPattern":"try {\n    client.describeObject(database, objectName);\n} catch (SalesforceConnectorException e) {\n    if (e.getMessage().contains(\"HTTP 401\")) {\n        refreshTokenAndRetry();\n    } else {\n        throw new IllegalArgumentException(\"Invalid Salesforce object: \" + objectName, e);\n    }\n}","preventionTips":["Verify object API names in Salesforce Setup before configuring table_path","Ensure the connected app has API access and the user View permissions on the object","Keep sessions alive / refresh tokens for long jobs","Smoke-test the describe endpoint with curl before running the pipeline"],"tags":["http","salesforce","api","rest"],"backgroundTag":"http-error-response","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}