didi/DoKit · error · IllegalArgumentException
Unexpected protocol: ${protocol}
Error message
Unexpected protocol: ${protocol} What it means
ObsoleteUrlFactory.open(URL, Proxy) inspects url.getProtocol() and only knows how to map "http" and "https" onto OkHttp connections; any other scheme falls through to IllegalArgumentException("Unexpected protocol: " + protocol). This factory is DoKit's replacement for okhttp3.JavaNetUrlFactory so that URL.openConnection() traffic is routed through OkHttp for capture.
Source
Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/aop/urlconnection/ObsoleteUrlFactory.java:158
*/
@Override
public ObsoleteUrlFactory clone() {
return new ObsoleteUrlFactory(client);
}
public HttpURLConnection open(URL url) {
return open(url, client.proxy());
}
HttpURLConnection open(URL url, @Nullable Proxy proxy) {
String protocol = url.getProtocol();
OkHttpClient copy = client.newBuilder()
.proxy(proxy)
.build();
if (protocol.equals("http")) return new OkHttpURLConnection(url, copy);
if (protocol.equals("https")) return new OkHttpsURLConnection(url, copy);
throw new IllegalArgumentException("Unexpected protocol: " + protocol);
}
/**
* Creates a URLStreamHandler as a {@link URL#setURLStreamHandlerFactory}.
*
* <p>This code configures OkHttp to handle all HTTP and HTTPS connections
* created with {@link URL#openConnection()}: <pre> {@code
*
* OkHttpClient okHttpClient = new OkHttpClient();
* URL.setURLStreamHandlerFactory(new ObsoleteUrlFactory(okHttpClient));
* }</pre>
*/
@Override
public URLStreamHandler createURLStreamHandler(final String protocol) {
if (!protocol.equals("http") && !protocol.equals("https")) return null;
return new URLStreamHandler() {
@OverrideView on GitHub (pinned to 626827cddb)
Solutions
- Avoid URL.openConnection() for non-http(s) schemes: use new FileInputStream(path) for files, or ClassLoader.getResourceAsStream() for classpath resources.
- Normalize the URL to http/https before openConnection() when the resource is actually served over HTTP.
- If you control the factory install, only install it for http/https or unset DoKit's URL-connection interception when non-HTTP protocols are needed.
Example fix
// before
InputStream in = new URL("file:///data/local/tmp/a.txt").openConnection().getInputStream();
// after
InputStream in = new FileInputStream("/data/local/tmp/a.txt"); Defensive patterns
Strategy: validation
Validate before calling
String p = url.getProtocol();
if (!("http".equals(p) || "https".equals(p))) {
throw new UnsupportedOperationException("unsupported scheme: " + p);
} Type guard
static boolean isHttpUrl(URL u) {
String p = u.getProtocol();
return "http".equals(p) || "https".equals(p);
} Try / catch
try { conn = factory.open(url); } catch (IllegalArgumentException e) { if (!isHttpUrl(url)) useNativeHandler(url); else throw e; } Prevention
- Route file: URLs to FileInputStream/ContentResolver, not openConnection().
- If a custom URLStreamHandlerFactory is installed globally, remember it intercepts every scheme.
When it happens
Trigger: Calling url.openConnection() (or open()) on a URL with a scheme like file:, ftp:, jar:, or a custom scheme while URL.setURLStreamHandlerFactory has installed this factory globally.
Common situations: DoKit installs the factory app-wide; later code opens a file: or jar: URL (very common for classpath resources, WebView assets, or local file access) and crashes because the factory intercepts every protocol.
Related errors
- source == null
- closed
- Cannot access request header fields after connection is set
- This protocol does not support input
- method does not support a request body: ${method}
AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14).
Data as JSON: /api/errors/58870ec1bf2de22d.
Report an issue: GitHub.