karatelabs/karate · warning
karate.properties is read-only, ignoring write of
Error message
karate.properties is read-only, ignoring write of '{}' — use System.setProperty() or Runner.Builder.systemProperty() to set one What it means
In Karate, the karate.properties map exposed to scripts is a read-only view over system properties. Writes via karate.put/putAll are no-ops: the map logs this warning telling the developer the write was ignored and to use System.setProperty() or Runner.Builder.systemProperty() instead. Scripts still read properties normally.
Solutions
- Use System.setProperty('key','value') (or in a feature: karate.setSystemProperty) to set a JVM system property
- Use Runner.Builder.systemProperty("key","value") to set properties at runner construction time
- Use karate.set('name', value) / scenario variables to share values within Karate instead of the properties map
- Remove the write entirely if the property was only meant for the same script (a variable suffices)
Example fix
// before (ignored, warns)
* karate.properties.put('my.flag', 'true')
// after
* karate.setSystemProperty('my.flag', 'true') Defensive patterns
Strategy: type-guard
Validate before calling
// detect a read-only properties view before writing
java.util.Map<String,String> props = karate.getProperties();
try { props.put("probe", "probe"); props.remove("probe"); System.out.println("writable"); }
catch (UnsupportedOperationException e) { System.out.println("read-only: use karate.setSystemProperty"); } Type guard
function propertiesAreWritable(){ try { karate.properties.__probe = 1; delete karate.properties.__probe; return true; } catch(e){ return false; } } Prevention
- Treat karate.properties as read-only by convention; never mutate it in shared utilities
- Use karate.setSystemProperty(...) inside features to set system properties
- Use Runner.Builder.systemProperty(...) for runner-level configuration
- Use karate.set(...) / scenario variables for values that only live inside the test
When it happens
Trigger: A feature or JS calls karate.properties.put('key','value') (or putAll) at runtime, or a script mutates the properties map returned from karate.properties.
Common situations: Porting old scripts that relied on writable karate.properties; tests trying to pass configuration to downstream code by writing a property mid-run; shared utilities that mutate properties instead of using karate.set / variables.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- at least one feature file is required
- boot.classpath(' '): expected a directory RELATIVE to the…
- boot.classpath: dir is null — pass a project-relative…
- boot.read: path is null
- Cannot assign to read only property
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/9d8e1cc213024623.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/core/Suite.java:1290
}
@Override
public boolean containsKey(Object key) {
if (overrides != null && overrides.containsKey(key)) {
return true;
}
return key instanceof String name && System.getProperty(name) != null;
}
/**
* {@code karate.properties['x'] = 'y'} has never set anything: it used to land in a
* throwaway copy and vanish. Kept a no-op rather than made to throw — a script doing it
* would start failing — but it is worth one line saying the write went nowhere, since
* silently losing it is how someone spends an afternoon.
*/
@Override
public String put(String key, String value) {
logger.warn("karate.properties is read-only, ignoring write of '{}'"
+ " — use System.setProperty() or Runner.Builder.systemProperty() to set one", key);
return get(key);
}
@Override
public Set<Entry<String, String>> entrySet() {
Map<String, String> merged = new HashMap<>();
System.getProperties().forEach((k, v) -> merged.put(k.toString(), v.toString()));
if (overrides != null) {
merged.putAll(overrides);
}
return merged.entrySet();
}
}
public DriverProvider getDriverProvider() {
return driverProvider;
}View on GitHub (pinned to a22eb90246)