elastic/elasticsearch · error · IllegalArgumentException

Database {} is read only

Error message

Database {} is read only

What it means

Thrown by PutDatabaseConfigurationAction.parseRequest when the database configuration being PUT uses a Provider whose isReadOnly() returns true. Only writable providers (currently Maxmind and Ipinfo) may be created via PUT. Read-only providers (Local, Web) are system-managed and cannot be authored by users.

Source

Thrown at modules/ip-location/src/main/java/org/elasticsearch/ingest/geoip/direct/PutDatabaseConfigurationAction.java:54

        public Request(TimeValue masterNodeTimeout, TimeValue ackTimeout, DatabaseConfiguration database) {
            super(masterNodeTimeout, ackTimeout);
            this.database = database;
        }

        public Request(StreamInput in) throws IOException {
            super(in);
            database = new DatabaseConfiguration(in);
        }

        public DatabaseConfiguration getDatabase() {
            return this.database;
        }

        public static Request parseRequest(TimeValue masterNodeTimeout, TimeValue ackTimeout, String id, XContentParser parser) {
            DatabaseConfiguration database = DatabaseConfiguration.parse(parser, id);
            if (database.isReadOnly()) {
                throw new IllegalArgumentException("Database " + id + " is read only");
            } else {
                return new Request(masterNodeTimeout, ackTimeout, database);
            }
        }

        @Override
        public void writeTo(StreamOutput out) throws IOException {
            super.writeTo(out);
            database.writeTo(out);
        }

        @Override
        public ActionRequestValidationException validate() {
            return database.validate();
        }

        @Override
        public int hashCode() {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Use a writable provider in the body: 'maxmind' (with account_id) or 'ipinfo'.
  2. If you intended a read-only database, note that Local and Web configs are managed by the system/downloader and cannot be PUT.
  3. Remove the 'local' or 'web' key from the request body and replace with 'maxmind' or 'ipinfo'.

Example fix

// before
PUT _ingest/geoip/database/my-db
{ "name": "City", "web": {} }

// after
PUT _ingest/geoip/database/my-db
{ "name": "City", "maxmind": { "account_id": "123456" } }
Defensive patterns

Strategy: validation

Validate before calling

// Only maxmind/ipinfo providers are writable via PUT
String provider = body.get("type"); // or detect the top-level key
Set<String> WRITABLE = Set.of("maxmind", "ipinfo");
if (!WRITABLE.contains(provider)) {
    throw new IllegalArgumentException("Provider " + provider + " is read-only; use maxmind or ipinfo");
}

Prevention

When it happens

Trigger: PUT _ingest/geoip/database/<id> with a request body whose provider is 'local' or 'web', e.g. {"name":"...","local":{"type":"..."}} or {"name":"...","web":{}}. The check fires during request parsing, before cluster state is touched.

Common situations: Misunderstanding which providers are user-writable; attempting to recreate a Local database seen in GET output; mixing up the GeoIP enterprise (web/local) databases with self-hosted Maxmind databases.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/95140b33d7696011. Report an issue: GitHub.