{"record":{"id":"bd369515f61b5585","repo":"microg/GmsCore","slug":"datapoint-already-built","errorCode":null,"errorMessage":"DataPoint already built","messagePattern":"DataPoint already built","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"play-services-fitness/src/main/java/com/google/android/gms/fitness/data/DataPoint.java","lineNumber":261,"sourceCode":"    }\n\n    /**\n     * Builder for {@link DataPoint} instances.\n     */\n    public static class Builder {\n        private final DataPoint dataPoint;\n        private boolean built = false;\n\n        Builder(DataSource dataSource) {\n            this.dataPoint = DataPoint.create(dataSource);\n        }\n\n        /**\n         * Builds and returns the {@link DataPoint}.\n         */\n        @NonNull\n        public DataPoint build() {\n            if (built) throw new IllegalStateException(\"DataPoint already built\");\n            this.built = true;\n            return this.dataPoint;\n        }\n\n        /**\n         * Sets the value of an activity field to {@code activity}.\n         *\n         * @throws IllegalArgumentException If the given index is out of the range for this data type.\n         * @throws IllegalStateException    If the field isn't of format {@link com.google.android.gms.fitness.data.Field#FORMAT_INT32}.\n         */\n        @NonNull\n        public Builder setActivityField(@NonNull com.google.android.gms.fitness.data.Field field, @NonNull String activity) {\n            if (built) throw new IllegalStateException(\"DataPoint already built\");\n            this.dataPoint.getValue(field).setActivity(activity);\n            return this;\n        }\n\n        /**","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-fitness/src/main/java/com/google/android/gms/fitness/data/DataPoint.java#L243-L279","documentation":"DataPoint.Builder.build() guards against reusing the same Builder after the DataPoint has already been produced. Once build() succeeds, the Builder's built flag is set and any further call to build() throws this IllegalStateException. Builders are single-use by design so the returned DataPoint cannot be mutated unexpectedly afterward.","triggerScenarios":"Calling build() twice on the same DataPoint.Builder instance, e.g. inside a loop where the Builder is hoisted outside the loop, or in code paths where build() can be reached twice (retry logic, conditional branches).","commonSituations":"A Builder stored in a field or closure and reused to emit multiple data points for a DataSet; accidentally calling build() both to validate and to produce the final object; helper methods that take a Builder and call build() at the end while the caller also calls build().","solutions":["Create a new DataPoint.Builder for each DataPoint you need instead of reusing one Builder.","Call build() exactly once, at the end of configuration, and store the returned DataPoint.","If you need many similar points, wrap construction in a helper method that builds a fresh Builder per call."],"exampleFix":"// before\nDataPoint.Builder b = DataPoint.builder(ds).setIntValues(1);\npoints.add(b.build());\npoints.add(b.build()); // IllegalStateException\n// after\nfor (int v : vals) {\n    points.add(DataPoint.builder(ds).setIntValues(v).build());\n}","handlingStrategy":"try-catch","validationCode":"if (builder == null || alreadyBuilt) {\n    builder = DataPoint.builder(dataSource); // fresh Builder instead of reuse\n}","typeGuard":"boolean isUsable(DataPoint.Builder b, Set<DataPoint.Builder> used) { return !used.contains(b); }","tryCatchPattern":"try {\n    return builder.build();\n} catch (IllegalStateException e) {\n    // Builder already consumed: create a new Builder and configure it again\n    builder = DataPoint.builder(dataSource);\n    return builder.setFloatValues(values).build();\n}","preventionTips":["Treat DataPoint.Builder as strictly single-use: build exactly once, at the end of configuration.","Create Builders inside the loop/scope that emits each data point; never store them in fields for reuse.","Write a helper method like newDataPoint(dataSource, values...) so reuse mistakes cannot happen."],"tags":["google-fit","fitness","illegal-state","builder-reuse","data-point"],"backgroundTag":"invalid-state-transition","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"}