didi/DoKit · error · ProtocolException
Expected one of " + METHODS + " but was " + method
Error message
Expected one of " + METHODS + " but was " + method
What it means
setRequestMethod() validates the method against a fixed METHODS set (the HTTP methods OkHttp's HttpURLConnection shim supports: GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE) and throws ProtocolException("Expected one of " + METHODS + " but was " + method) for anything else. Custom methods like PATCH or PROPFIND are not accepted.
Source
Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/aop/urlconnection/ObsoleteUrlFactory.java:725
@Override
public void addRequestProperty(String field, String value) {
if (connected) {
throw new IllegalStateException("Cannot add request property after connection is made");
}
if (field == null) {
throw new NullPointerException("field == null");
}
if (value == null) {
return;
}
requestHeaders.add(field, value);
}
@Override
public void setRequestMethod(String method) throws ProtocolException {
if (!METHODS.contains(method)) {
throw new ProtocolException("Expected one of " + METHODS + " but was " + method);
}
this.method = method;
}
@Override
public void setFixedLengthStreamingMode(int contentLength) {
setFixedLengthStreamingMode((long) contentLength);
}
@Override
public void setFixedLengthStreamingMode(long contentLength) {
if (super.connected) throw new IllegalStateException("Already connected");
if (chunkLength > 0) throw new IllegalStateException("Already in chunked mode");
if (contentLength < 0) throw new IllegalArgumentException("contentLength < 0");
this.fixedContentLength = contentLength;
super.fixedContentLength = (int) Math.min(contentLength, Integer.MAX_VALUE);
}
View on GitHub (pinned to 626827cddb)
Solutions
- For PATCH specifically, send POST with an X-HTTP-Method-Override: PATCH header, or use OkHttp's Request.Builder.method("PATCH", body) directly which supports arbitrary methods.
- Verify the method string: exact uppercase, no surrounding whitespace, matches one of GET/POST/HEAD/OPTIONS/PUT/DELETE/TRACE.
- Constant-define method names instead of building them dynamically.
Example fix
// before
conn.setRequestMethod("PATCH"); // ProtocolException
// after
conn.setRequestMethod("POST");
conn.setRequestProperty("X-HTTP-Method-Override", "PATCH");
// or use OkHttp directly:
// Request req = new Request.Builder().url(u).method("PATCH", body).build(); Defensive patterns
Strategy: validation
Validate before calling
Set<String> OK = new HashSet<>(Arrays.asList("GET","POST","HEAD","OPTIONS","PUT","DELETE","TRACE"));
String m = method.trim().toUpperCase(Locale.US);
if (!OK.contains(m)) { /* use OkHttp Request.Builder or POST + X-HTTP-Method-Override */ } Type guard
static boolean isSupportedUrlConnectionMethod(String m) {
return Arrays.asList("GET","POST","HEAD","OPTIONS","PUT","DELETE","TRACE").contains(m);
} Prevention
- Remember PATCH is NOT supported via HttpURLConnection.setRequestMethod — plan for POST+override or OkHttp.
- Normalize method strings to uppercase without whitespace before setting.
When it happens
Trigger: setRequestMethod("PATCH") — the classic case, since PATCH is not in the set; typos like "post" (lowercase) or "GET " (trailing space); custom WebDAV methods.
Common situations: Migrating a POST endpoint to PATCH; copy-pasted method strings with wrong case; REST wrappers exposing arbitrary verbs.
Related errors
- Cannot access request header fields after connection is set
- This protocol does not support input
- method does not support a request body: ${method}
- cannot write request body after response has been read
- ${method} does not support writing
AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14).
Data as JSON: /api/errors/85a57daf13f72d42.
Report an issue: GitHub.