{"record":{"id":"d7da7fb531c5bfee","repo":"microg/GmsCore","slug":"transition-types-not-set","errorCode":null,"errorMessage":"Transition types not set.","messagePattern":"Transition types not set\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"play-services-location/src/main/java/com/google/android/gms/location/Geofence.java","lineNumber":114,"sourceCode":"        private double latitude;\n        private double longitude;\n        private float radius;\n        private long expirationTime = Long.MIN_VALUE;\n        private int loiteringDelay = -1;\n        private int notificationResponsiveness;\n        private String requestId;\n        private @TransitionTypes int transitionTypes;\n\n        /**\n         * Creates a geofence object.\n         *\n         * @throws IllegalArgumentException if any parameters are not set or out of range\n         */\n        public Geofence build() throws IllegalArgumentException {\n            if (requestId == null) {\n                throw new IllegalArgumentException(\"Request ID not set.\");\n            } else if (transitionTypes == 0) {\n                throw new IllegalArgumentException(\"Transition types not set.\");\n            } else if ((transitionTypes & GEOFENCE_TRANSITION_DWELL) > 0 && loiteringDelay < 0) {\n                throw new IllegalArgumentException(\"Non-negative loitering delay needs to be set when transition types include GEOFENCE_TRANSITION_DWELLING.\");\n            } else if (expirationTime == Long.MIN_VALUE) {\n                throw new IllegalArgumentException(\"Expiration not set.\");\n            } else if (regionType == -1) {\n                throw new IllegalArgumentException(\"Geofence region not set.\");\n            } else if (notificationResponsiveness < 0) {\n                throw new IllegalArgumentException(\"Notification responsiveness should be nonnegative.\");\n            } else {\n                return new ParcelableGeofence(requestId, expirationTime, regionType, latitude, longitude, radius, transitionTypes, notificationResponsiveness, loiteringDelay);\n            }\n        }\n\n        /**\n         * Sets the region of this geofence. The geofence represents a circular area on a flat, horizontal plane.\n         *\n         * @param latitude  latitude in degrees, between -90 and +90 inclusive\n         * @param longitude longitude in degrees, between -180 and +180 inclusive","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-location/src/main/java/com/google/android/gms/location/Geofence.java#L96-L132","documentation":"Geofence.Builder.build() validates that transition types were configured before constructing the geofence. transitionTypes defaults to 0, meaning no GEOFENCE_TRANSITION_ENTER/EXIT/DWELL events were requested, so the geofence would be meaningless to monitor. The library throws IllegalArgumentException to fail fast at build time.","triggerScenarios":"Calling Geofence.Builder.build() without calling setTransitionTypes(int) (or calling it with 0). The check fires when transitionTypes == 0.","commonSituations":"Copy-pasting builder snippets that omit setTransitionTypes; constructing a geofence incrementally and forgetting the transition call; refactoring where the constant passed was accidentally 0.","solutions":["Call setTransitionTypes() on the builder with at least one of Geofence.GEOFENCE_TRANSITION_ENTER, GEOFENCE_TRANSITION_EXIT, or GEOFENCE_TRANSITION_DWELL before calling build()","Verify the int value passed is a non-zero combination of the GEOFENCE_TRANSITION_* constants"],"exampleFix":"// before\nGeofence fence = new Geofence.Builder()\n    .setRequestId(\"fence1\")\n    .setCircularRegion(lat, lng, radius)\n    .setExpirationDuration(600000)\n    .build();\n// after\nGeofence fence = new Geofence.Builder()\n    .setRequestId(\"fence1\")\n    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)\n    .setCircularRegion(lat, lng, radius)\n    .setExpirationDuration(600000)\n    .build();","handlingStrategy":"validation","validationCode":"if (transitionTypes == 0) throw new IllegalStateException(\"Call setTransitionTypes() before build()\");\nGeofence fence = builder.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT).build();","typeGuard":"static boolean hasTransitionTypes(int t) { return t != 0; }","tryCatchPattern":"try { return builder.build(); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"Transition types\")) { builder.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT); return builder.build(); } throw e; }","preventionTips":["Always include setTransitionTypes() in your Geofence builder helper/wrapper","Build geofences through a single factory method so required calls are never skipped"],"tags":["geofencing","validation","android","builder"],"backgroundTag":"missing-required-argument","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"}