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

  1. Load the config from a file-based source (ConfigSource.FileConfigSource) or the default config location before persisting
  2. Call persist(Path) explicitly with the target file instead of relying on the original source
  3. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/ce17189d05c11e1e. Report an issue: GitHub.