{"record":{"id":"e3ebb4cc4bdf4267","repo":"apache/iceberg","slug":"received-a-malformed-path-for-a-rest-request-s","errorCode":null,"errorMessage":"Received a malformed path for a REST request: %s. Paths should not start with /","messagePattern":"Received a malformed path for a REST request: (.+?)\\. Paths should not start with /","errorType":"validation","errorClass":"RESTException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/rest/HTTPRequest.java","lineNumber":127,"sourceCode":"        throw new RESTException(e, \"Failed to encode request body: %s\", body);\n      }\n    }\n    return null;\n  }\n\n  /**\n   * Returns the {@link ObjectMapper} to use for encoding the request body. The default is {@link\n   * RESTObjectMapper#mapper()}.\n   */\n  @Value.Default\n  default ObjectMapper mapper() {\n    return RESTObjectMapper.mapper();\n  }\n\n  @Value.Check\n  default void check() {\n    if (path().startsWith(\"/\")) {\n      throw new RESTException(\n          \"Received a malformed path for a REST request: %s. Paths should not start with /\",\n          path());\n    }\n\n    if (baseUri() == null && !hasAbsolutePath()) {\n      throw new RESTException(\n          \"Received a request with a relative path and no base URI: %s\", path());\n    }\n  }\n\n  private boolean hasAbsolutePath() {\n    return path().startsWith(\"https://\") || path().startsWith(\"http://\");\n  }\n}\n","sourceCodeStart":109,"sourceCodeEnd":142,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/rest/HTTPRequest.java#L109-L142","documentation":"HTTPRequest's @Value.Check validates the request at construction. A path starting with '/' is rejected with this RESTException because the client joins the path onto the base URI itself; a leading slash would produce a malformed or wrong URL. The check also rejects relative paths when no base URI is configured.","triggerScenarios":"Calling HTTPRequest.post(\"/v1/namespaces\") or .get(\"/tables/x\") — any path with a leading slash; also building a request without a base URI set while the path is not absolute.","commonSituations":"Copy-pasting a full URL path (with leading slash) from API docs into a client request; building paths by string concatenation where an earlier part already ends in '/'; using HTTPRequest without configuring the client's base URI.","solutions":["Remove the leading '/' from the request path (paths must be relative, e.g. \"v1/namespaces\").","Strip leading slashes programmatically when paths are built from variables or user input.","Set the client's base URI via HTTPClient.Builder.uri(...) when using relative paths.","Use RESTUtil.stripLeadingSlash or equivalent before constructing the request."],"exampleFix":"// before\nHTTPRequest.get(\"/v1/namespaces\");\n// after\nHTTPRequest.get(RESTUtil.stripLeadingSlash(\"/v1/namespaces\")); // \"v1/namespaces\"","handlingStrategy":"validation","validationCode":"String p = rawPath;\nif (p.startsWith(\"/\")) p = p.substring(1);\nPreconditions.checkArgument(!p.startsWith(\"/\"), \"path must be relative\");\nHTTPRequest.get(p);","typeGuard":null,"tryCatchPattern":"try {\n  HTTPRequest.get(path);\n} catch (RESTException e) {\n  if (e.getMessage().contains(\"should not start with /\")) {\n    // strip the leading slash and rebuild the request\n  }\n  throw e;\n}","preventionTips":["Never start request paths with '/'; strip it when paths come from variables.","Configure the client base URI and keep request paths relative.","Add a unit test that builds every request path your code uses."],"tags":["rest-catalog","url","validation","immutables"],"backgroundTag":"invalid-url-format","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}