Yalantis/uCrop · error · NullPointerException

OutputStream for given output Uri is null

Error message

OutputStream for given output Uri is null

What it means

In BitmapLoadTask.downloadFile, after a successful HTTP response, the output stream obtained for the destination Uri was null, so nothing could be written; the task throws this NullPointerException. This means the content resolver (for content:// output) or file stream creation produced no writable stream.

Source

Thrown at ucrop/src/main/java/com/yalantis/ucrop/task/BitmapLoadTask.java:237

            Request request = new Request.Builder()
                .url(inputUri.toString())
                .build();
            response = client.newCall(request).execute();
            source = response.body().source();

            OutputStream outputStream;

            if (isContentUri(mOutputUri)) {
                outputStream = mContext.getContentResolver().openOutputStream(outputUri);
            } else {
                outputStream = new FileOutputStream(new File(outputUri.getPath()));
            }

            if (outputStream != null) {
                sink = Okio.sink(outputStream);
                source.readAll(sink);
            } else {
                throw new NullPointerException("OutputStream for given output Uri is null");
            }
        } finally {
            BitmapLoadUtils.close(source);
            BitmapLoadUtils.close(sink);
            if (response != null) {
                BitmapLoadUtils.close(response.body());
            }
            client.dispatcher().cancelAll();

            // swap uris, because input image was downloaded to the output destination
            // (cropped image will override it later)
            mInputUri = mOutputUri;
        }
    }

    @Override
    protected void onPostExecute(@NonNull BitmapWorkerResult result) {
        if (result.mBitmapWorkerException == null) {

View on GitHub (pinned to f788b534b4)

Solutions

  1. Ensure the output content Uri is writable: use ContentResolver.openOutputStream(uri, "w") semantics via a provider that supports writing.
  2. Write to an app-owned file instead (getExternalFilesDir/getCacheDir) and pass Uri.fromFile.
  3. For MediaStore, insert a proper entry with the correct MIME type before using its Uri as output.
  4. Grant FLAG_GRANT_WRITE_URI_PERMISSION when handing a provider Uri to uCrop.

Example fix

// before
Uri out = Uri.parse("content://com.example.fileprovider/readonly/out.jpg");
UCrop.of(sourceUri, out).start(this);
// after
Uri out = Uri.fromFile(new File(getExternalFilesDir(null), "cropped.jpg"));
UCrop.of(sourceUri, out).start(this);
Defensive patterns

Strategy: try-catch

Validate before calling

boolean isWritable(Uri uri) {
    if (uri == null) return false;
    if ("file".equals(uri.getScheme())) {
        java.io.File f = new java.io.File(uri.getPath());
        return f.getParentFile() != null && f.getParentFile().canWrite();
    }
    try (OutputStream os = getContentResolver().openOutputStream(uri)) {
        return os != null;
    } catch (Exception e) { return false; }
}

Type guard

boolean isWritableDestination(android.net.Uri uri) {
    return uri != null && ("file".equals(uri.getScheme()) || isWritable(uri));
}

Try / catch

try {
    UCrop.of(remoteUri, outputUri).start(activity);
} catch (Exception e) {
    Log.e(TAG, "Cannot write crop output to " + outputUri, e);
}

Prevention

When it happens

Trigger: Download destination Uri is a content:// Uri whose provider returns null from openOutputStream (e.g. wrong MIME/mode, read-only provider), or a file Uri whose path cannot be opened — surfaced as a null stream right before Okio.sink().

Common situations: Writing crops into a MediaStore/DocumentsProvider URI opened without "w" mode support; destination in read-only external storage; FileProvider URI that only grants read permission.

Related errors


AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08). Data as JSON: /api/errors/3e4b4d54b33c700b. Report an issue: GitHub.