Tencent/QMUI_Android · error · IOException
Failed to create new MediaStore record.
Error message
Failed to create new MediaStore record.
What it means
saveToStore inserts a new MediaStore.Images record via ContentResolver.insert(). When the MediaStore provider returns null (insert rejected), an IOException("Failed to create new MediaStore record.") is thrown because no target Uri exists to write the image into.
Source
Thrown at photo/src/main/java/com/qmuiteam/photo/util/QMUIPhotoHelper.kt:67
writer: (OutputStream) -> Unit
): Uri? {
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, name)
put(MediaStore.MediaColumns.DATE_ADDED, System.currentTimeMillis())
put(MediaStore.MediaColumns.MIME_TYPE, mimeType)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
put(MediaStore.MediaColumns.RELATIVE_PATH, dirName)
put(MediaStore.MediaColumns.IS_PENDING, 1)
}
}
val contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
var stream: OutputStream? = null
var uri: Uri? = null
try {
uri = context.contentResolver.insert(contentUri, contentValues)
if (uri == null) {
throw IOException("Failed to create new MediaStore record.")
}
stream = context.contentResolver.openOutputStream(uri)
if (stream == null) {
throw IOException("Failed to get output stream.")
}
writer.invoke(stream)
contentValues.clear()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0)
context.contentResolver.update(uri, contentValues, null, null)
}
return uri
} catch (e: Throwable) {
Log.i(TAG, "saveToStore failed.", e)
if (uri != null) {
context.contentResolver.delete(uri, null, null)
}
} finally {View on GitHub (pinned to 026e7d4866)
Solutions
- Request READ/WRITE_EXTERNAL_STORAGE runtime permission on API <= 28 before saving.
- Verify external storage state via Environment.getExternalStorageState() == MEDIA_MOUNTED.
- Check free disk space and retry when storage is available.
- Catch the IOException and surface a user-facing save failure.
Example fix
// before
QMUIPhotoHelper.saveToStore(context, ...) // no permission requested
// after
requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQ) { QMUIPhotoHelper.saveToStore(context, ...) } Defensive patterns
Strategy: try-catch
Validate before calling
if (Build.VERSION.SDK_INT < 29 && ContextCompat.checkSelfPermission(context, WRITE_EXTERNAL_STORAGE) != PERMISSION_GRANTED) return if (Environment.getExternalStorageState() != Environment.MEDIA_MOUNTED) return
Try / catch
try { saveToStore(context, contentValues, writer) } catch (e: IOException) { showSaveFailedToast(e) } Prevention
- Request storage permissions on API <= 28 before saving
- Check Environment.getExternalStorageState() == MEDIA_MOUNTED
- Monitor free disk space
When it happens
Trigger: contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) returning null — typically missing WRITE_EXTERNAL_STORAGE (pre-Q) or volume unavailable/readonly.
Common situations: Saving a photo without storage permission on Android 9 or lower; external storage mounted as read-only (USB/SD emulation); device storage full or provider crash.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Failed to get output stream.
- Can not perform LatestVisitRecord, %s must be annotated by L
- Fragment(%s) not attached to Activity.
- Can not find the fragment container provider.
- requestCode can not be %s
AI-assisted analysis of Tencent/QMUI_Android@026e7d4866 (2026-09-06).
Data as JSON: /api/errors/86581d489575bf66.
Report an issue: GitHub.