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
- Use a writable provider in the body: 'maxmind' (with account_id) or 'ipinfo'.
- If you intended a read-only database, note that Local and Web configs are managed by the system/downloader and cannot be PUT.
- 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
- Remember only 'maxmind' and 'ipinfo' are user-writable providers.
- Local and Web databases are system-managed; do not attempt to PUT them.
- When templating PUT bodies, restrict the provider field to writable values.
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
- Database {} is read only
- invalid database configuration id [{}]: must not be null or
- invalid database configuration id [{}]: id doesn't match req
- wildcard only supports a single value, please use comma-sepa
- database [%s] is already being downloaded via configuration
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/95140b33d7696011.
Report an issue: GitHub.