microg/GmsCore · error · IllegalArgumentException

streamName must be set

Error message

streamName must be set

What it means

Thrown by DataSource.Builder.setStreamName when a null stream name is passed. The stream identifier distinguishes multiple data sources of the same type, and the API requires it to be a non-null String. Unlike build(), this is an IllegalArgumentException — the argument itself is invalid, not the builder state.

Source

Thrown at play-services-fitness/src/main/java/com/google/android/gms/fitness/data/DataSource.java:266

        public Builder setDevice(@NonNull Device device) {
            this.device = device;
            return this;
        }

        /**
         * The stream name uniquely identifies this particular data source among other data sources of the same type from the same underlying
         * producer. Setting the stream name is optional, but should be done whenever an application exposes two streams for the same data type, or
         * when a device has two equivalent sensors.
         * <p>
         * The stream name is used by {@link DataSource#getStreamIdentifier()} to make sure the different streams are properly separated when
         * querying or persisting data.
         *
         * @throws IllegalArgumentException If the specified stream name is null.
         */
        @NonNull
        public Builder setStreamName(@NonNull String streamName) {
            //noinspection ConstantValue
            if (streamName == null) throw new IllegalArgumentException("streamName must be set");
            this.streamName = streamName;
            return this;
        }

        /**
         * Sets the type of the data source. {@link DataSource#TYPE_DERIVED} should be used if any other data source is used in generating the data.
         * {@link DataSource#TYPE_RAW} should be used if the data comes completely from outside of Google Fit.
         */
        @NonNull
        public Builder setType(int type) {
            this.type = type;
            return this;
        }
    }

    public static final SafeParcelableCreatorAndWriter<DataSource> CREATOR = findCreator(DataSource.class);

}

View on GitHub (pinned to 157c9d86ac)

Solutions

  1. Provide a descriptive constant stream name, e.g. setStreamName("my_app.step_counter").
  2. Null-check or requireNonNull the source value before calling setStreamName.
  3. If the name comes from config, fail fast with a clear error when config is absent.
  4. Use a default fallback name when the configured name is null/blank.

Example fix

// before
String name = config.getStreamName(); // may be null
builder.setStreamName(name); // throws when null
// after
String name = config.getStreamName();
if (name == null) name = "default.step_stream";
builder.setStreamName(name);
Defensive patterns

Strategy: type-guard

Validate before calling

if (streamName == null || streamName.isEmpty()) { streamName = "default." + dataType.getName(); }

Type guard

String requireStreamName(String s) { return (s != null && !s.isEmpty()) ? s : "default.stream"; }

Try / catch

try { builder.setStreamName(name); } catch (IllegalArgumentException e) { builder.setStreamName("default.stream"); }

Prevention

When it happens

Trigger: Passing a null String to setStreamName, typically from a variable that is null: a missing config value, an unresolvable resource string, or a null return from a lookup.

Common situations: Stream names read from Settings/RemoteConfig that were never configured; null results from string resources or database lookups; Kotlin/Java interop where a platform type silently allowed null.

Related errors


AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06). Data as JSON: /api/errors/a225b9fd854c7ea2. Report an issue: GitHub.