{"record":{"id":"5898c95ac7f416e6","repo":"microg/GmsCore","slug":"could-not-find-suitable-preview-frames-per-second","errorCode":null,"errorMessage":"Could not find suitable preview frames per second range.","messagePattern":"Could not find suitable preview frames per second range\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"play-services-vision-common/src/main/java/com/google/android/gms/vision/CameraSource.java","lineNumber":371,"sourceCode":"        }\n        throw new IOException(\"Could not find requested camera.\");\n    }\n\n    private int[] pickFpsRange(Camera camera) throws IOException {\n        int requestsFpms = (int) (requestedFps * 1000.0F);\n        int[] selectedFpsRange = null;\n        int selectedPreviewFpsOffset = Integer.MAX_VALUE;\n\n        for (int[] previewFpsRange : camera.getParameters().getSupportedPreviewFpsRange()) {\n            int minOffset = requestsFpms - previewFpsRange[0];\n            int maxOffset = requestsFpms - previewFpsRange[1];\n            int previewFpsOffset;\n            if ((previewFpsOffset = Math.abs(minOffset) + Math.abs(maxOffset)) < selectedPreviewFpsOffset) {\n                selectedFpsRange = previewFpsRange;\n                selectedPreviewFpsOffset = previewFpsOffset;\n            }\n        }\n        if (selectedFpsRange == null) throw new IOException(\"Could not find suitable preview frames per second range.\");\n        return selectedFpsRange;\n    }\n\n    private SizePair pickCameraSize(Camera camera) throws IOException {\n        ArrayList<SizePair> sizeCandidates = new ArrayList<>();\n        for (Camera.Size previewSize : camera.getParameters().getSupportedPreviewSizes()) {\n            float previewAspectRatio = (float) (previewSize).width / (float) previewSize.height;\n            for (Camera.Size pictureSize : camera.getParameters().getSupportedPictureSizes()) {\n                float pictureAspectRatio = (float) (pictureSize).width / (float) pictureSize.height;\n                if (Math.abs(previewAspectRatio - pictureAspectRatio) < 0.01F) { // Approximately same aspect ratio\n                    sizeCandidates.add(new SizePair(previewSize, pictureSize));\n                    break;\n                }\n            }\n        }\n        if (sizeCandidates.size() == 0) {\n            for (Camera.Size previewSize : camera.getParameters().getSupportedPreviewSizes()) {\n                sizeCandidates.add(new SizePair(previewSize, null));","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-vision-common/src/main/java/com/google/android/gms/vision/CameraSource.java#L353-L389","documentation":"CameraSource.pickFpsRange() scans the camera's supported preview FPS ranges for one closest to the requested FPS and throws IOException if none was selected (selectedFpsRange remains null). This means the camera exposes no usable supportedPreviewFpsRange entries compatible with the request.","triggerScenarios":"Calling start() when the device's Camera.Parameters.getSupportedPreviewFpsRange() returns no ranges (empty/unavailable), leaving selectedFpsRange null after the selection loop.","commonSituations":"Virtual emulators or exotic camera HALs reporting no FPS ranges; drivers returning malformed empty lists; requesting FPS outside everything the device supports.","solutions":["Check camera.getParameters().getSupportedPreviewFpsRange() for emptiness before start() and choose a fallback camera/facing","Adjust requestedFps to a standard value (e.g. 30) that devices commonly support","Test on the failing device and log getSupportedPreviewFpsRange() to see what is exposed","Catch IOException around start() and degrade gracefully (show a camera-unavailable state)"],"exampleFix":"// before\nCameraSource source = new CameraSource.Builder(context, detector)\n    .setRequestedFps(60.0f)\n    .build();\nsource.start(); // may throw if no suitable fps range\n// after\ntry {\n    CameraSource source = new CameraSource.Builder(context, detector)\n        .setRequestedFps(30.0f)\n        .build();\n    source.start();\n} catch (IOException e) {\n    Log.e(TAG, \"No suitable preview FPS range on this device\", e);\n}","handlingStrategy":"try-catch","validationCode":"List<int[]> ranges = camera.getParameters().getSupportedPreviewFpsRange();\nif (ranges == null || ranges.isEmpty()) { /* pick a different camera or fail gracefully */ }","typeGuard":"null","tryCatchPattern":"try {\n    cameraSource.start();\n} catch (IOException e) {\n    // no usable FPS range: degrade or switch camera\n}","preventionTips":["Use standard FPS values (30) that devices reliably support","Log getSupportedPreviewFpsRange() when debugging device-specific failures","Always wrap start() in IOException handling on untested hardware"],"tags":["vision","camera","fps","io"],"backgroundTag":"resource-not-found","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}