quarkusio/quarkus · error · UnsupportedOperationException
Can not write configuration as it was read from an alternate
Error message
Can not write configuration as it was read from an alternate source: ${source} What it means
persistConfigSource refuses to write the registries configuration when it was loaded from a source that has no backing file path (e.g. an in-memory stream, reader, or synthesized default config source). Writing back would silently overwrite nothing or the wrong file, so it fails fast with UnsupportedOperationException.
Source
Thrown at independent-projects/tools/registry-client/src/main/java/io/quarkus/registry/config/RegistriesConfigImpl.java:223
public int hashCode() {
return Objects.hash(debug, registries);
}
@Override
public String toString() {
return this.getClass().getSimpleName() +
"{debug=" + debug +
", registries=" + registries +
", configSource=" + configSource +
'}';
}
static void persistConfigSource(RegistriesConfigImpl config) throws IOException {
Path targetFile = config.configSource.getFilePath();
if (config.configSource == ConfigSource.DEFAULT) {
targetFile = RegistriesConfigLocator.getDefaultConfigYamlLocation();
} else if (targetFile == null) {
throw new UnsupportedOperationException(
String.format("Can not write configuration as it was read from an alternate source: %s",
config.configSource.describe()));
}
config.persist(targetFile);
}
static class Serializer extends ValueSerializer<RegistriesConfigImpl> {
@Override
public void serialize(RegistriesConfigImpl value, JsonGenerator gen, SerializationContext ctxt) {
boolean isDefaultDebug = !value.debug;
boolean isDefaultList = RegistryConfigImpl.isDefaultList(value.registries);
if (isDefaultDebug && isDefaultList) {
gen.writeNumber("");
} else {
gen.writeStartObject();
if (gen instanceof YAMLGenerator) {
if (!isDefaultDebug) {View on GitHub (pinned to e1c734241f)
Solutions
- Load the config from a file-based source (ConfigSource.FileConfigSource) or the default config location before persisting
- Call persist(Path) explicitly with the target file instead of relying on the original source
- If using load(InputStream/Reader), track the originating file yourself and persist to that path
Example fix
// before
RegistriesConfig cfg = RegistriesConfigLocator.load(stream);
RegistriesConfigImpl.persistConfigSource((RegistriesConfigImpl) cfg); // throws
// after
RegistriesConfigImpl.persistConfigSource(
(RegistriesConfigImpl) RegistriesConfigLocator.loadDefault()); // or persist(Path) Defensive patterns
Strategy: type-guard
Type guard
boolean isPersistable(RegistriesConfigImpl cfg) {
return cfg.configSource == ConfigSource.DEFAULT || cfg.configSource.getFilePath() != null;
} Try / catch
try { RegistriesConfigImpl.persistConfigSource(cfg); } catch (UnsupportedOperationException e) { if (e.getMessage().startsWith("Can not write configuration")) { persistToExplicitPath(cfg, userConfigPath); } else throw e; } Prevention
- Only persist configs loaded from file/default sources
- For stream-loaded configs, call persist(Path) with a known target
- Track the origin of configs loaded via load(InputStream/Reader)
When it happens
Trigger: Calling persistConfigSource (via persist) on a RegistriesConfigImpl whose ConfigSource is an alternate (getFilePath() == null and not ConfigSource.DEFAULT) — typically after load(InputStream)/load(Reader).
Common situations: Tools that load registry config from a custom stream and then try to save user changes (e.g. `quarkus registry add-config` style flows) without knowing where to write.
Related errors
- Failed to load bootstrap classloading config from applicatio
- Failed to parse ${extensionFile}
- Failed to open path tree with root %s
- Failed to load application configuration
- Failed to read %s
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/ce17189d05c11e1e.
Report an issue: GitHub.