Configuration files can change in ways that are incompatible with older application versions.
This happened after changing persistent alarm grace periods from plain seconds to values with time suffixes. A new configuration containing:
PERSISTENT:12h
was accidentally loaded by an older compiled JAR. Instead of clearly reporting an incompatible configuration format, the old parser failed with an unrelated NumberFormatException.
We need a simple and explicit way to verify that a configuration file is compatible with the parser loading it.
Proposed solution
Every configuration file format must contain a format version near the top of the file:
FORMAT_VERSION=1
Blank lines and comments may appear before the declaration, but it must be the first actual configuration entry.
The corresponding parser or configuration loader must contain its supported format version as a hardcoded constant:
privatestaticfinalintSUPPORTED_FORMAT_VERSION=1;
Before parsing any other content, the loader must compare the file version with its supported version.
The versions must match exactly. Otherwise, configuration loading and application startup must be aborted.
Independent versions
Each configuration format must have its own version number.
For example, a breaking change to alarms.conf must not require incrementing the version of alarmaction_Pushover.conf.
The version is incremented only when a change is incompatible with the previous file format. Compatible additions do not require a new version.
When making a breaking configuration change, both of the following must be updated:
The hardcoded supported version in the corresponding parser.
The version declared in the configuration file and its example file.
Scope
Apply format-version validation to all human-maintained runtime configuration files and their corresponding loaders.
All active configuration loaders must be inventoried during implementation. The scope must not be limited to classes whose names end with ConfigurationParser, since some files may be parsed directly by another class.
A shared helper may be used for reading and validating the declaration, but the supported version must remain independently defined for each configuration format.
Validation
Configuration loading must fail if:
FORMAT_VERSION is missing.
The declaration occurs more than once.
The value is not a positive integer.
The file version differs from the parser version.
Another configuration entry occurs before the version declaration.
The version must be validated before the rest of the file is parsed.
Error message
A mismatch must produce a clear error containing:
The configuration file path.
The version found in the file.
The version supported by the running parser.
An explanation that the configuration file and application are incompatible.
A suggestion to update the configuration file or compile/deploy the correct application version.
Example:
Configuration format version mismatch in conf/alarms.conf:
File version: 2
Supported version: 1
The configuration file and the running application are not compatible.
Update the configuration file or compile and deploy the correct application version.
Documentation and examples
Add FORMAT_VERSION=1 to every current example configuration.
Update the relevant documentation to describe the format-version mechanism.
Document that versions are independent per configuration format.
Document that the version must be incremented on both sides when making a breaking format change.
Acceptance criteria
Every active runtime configuration format contains a FORMAT_VERSION declaration.
Every corresponding parser or loader has a hardcoded supported format version.
The version is checked before any other configuration content is parsed.
File and parser versions must match exactly.
A missing, duplicate, malformed or misplaced declaration aborts startup with a clear error.
A newer configuration file is rejected by an older parser.
An older configuration file is rejected by a newer parser after a breaking format change.
Each configuration format can be versioned independently.
All example configuration files are updated.
The format-version policy is documented.
The project compiles and starts successfully with matching configuration versions.
## Background
Configuration files can change in ways that are incompatible with older application versions.
This happened after changing persistent alarm grace periods from plain seconds to values with time suffixes. A new configuration containing:
```text
PERSISTENT:12h
```
was accidentally loaded by an older compiled JAR. Instead of clearly reporting an incompatible configuration format, the old parser failed with an unrelated `NumberFormatException`.
We need a simple and explicit way to verify that a configuration file is compatible with the parser loading it.
## Proposed solution
Every configuration file format must contain a format version near the top of the file:
```text
FORMAT_VERSION=1
```
Blank lines and comments may appear before the declaration, but it must be the first actual configuration entry.
The corresponding parser or configuration loader must contain its supported format version as a hardcoded constant:
```java
private static final int SUPPORTED_FORMAT_VERSION = 1;
```
Before parsing any other content, the loader must compare the file version with its supported version.
The versions must match exactly. Otherwise, configuration loading and application startup must be aborted.
## Independent versions
Each configuration format must have its own version number.
For example, a breaking change to `alarms.conf` must not require incrementing the version of `alarmaction_Pushover.conf`.
The version is incremented only when a change is incompatible with the previous file format. Compatible additions do not require a new version.
When making a breaking configuration change, both of the following must be updated:
1. The hardcoded supported version in the corresponding parser.
2. The version declared in the configuration file and its example file.
## Scope
Apply format-version validation to all human-maintained runtime configuration files and their corresponding loaders.
This includes at least:
* `alarms.conf`
* `alarmaction_Console.conf`
* `alarmaction_Pushover.conf`
* `alarmaction_JupiterPerpsPositionIncreaseAlarmAction.conf`
* `alarmaction_JupiterPerpsPositionDecreaseAlarmAction.conf`
* `evelyn.conf`
* `positions.conf`
All active configuration loaders must be inventoried during implementation. The scope must not be limited to classes whose names end with `ConfigurationParser`, since some files may be parsed directly by another class.
A shared helper may be used for reading and validating the declaration, but the supported version must remain independently defined for each configuration format.
## Validation
Configuration loading must fail if:
* `FORMAT_VERSION` is missing.
* The declaration occurs more than once.
* The value is not a positive integer.
* The file version differs from the parser version.
* Another configuration entry occurs before the version declaration.
The version must be validated before the rest of the file is parsed.
## Error message
A mismatch must produce a clear error containing:
* The configuration file path.
* The version found in the file.
* The version supported by the running parser.
* An explanation that the configuration file and application are incompatible.
* A suggestion to update the configuration file or compile/deploy the correct application version.
Example:
```text
Configuration format version mismatch in conf/alarms.conf:
File version: 2
Supported version: 1
The configuration file and the running application are not compatible.
Update the configuration file or compile and deploy the correct application version.
```
## Documentation and examples
* Add `FORMAT_VERSION=1` to every current example configuration.
* Update the relevant documentation to describe the format-version mechanism.
* Document that versions are independent per configuration format.
* Document that the version must be incremented on both sides when making a breaking format change.
## Acceptance criteria
* [ ] Every active runtime configuration format contains a `FORMAT_VERSION` declaration.
* [ ] Every corresponding parser or loader has a hardcoded supported format version.
* [ ] The version is checked before any other configuration content is parsed.
* [ ] File and parser versions must match exactly.
* [ ] A missing, duplicate, malformed or misplaced declaration aborts startup with a clear error.
* [ ] A newer configuration file is rejected by an older parser.
* [ ] An older configuration file is rejected by a newer parser after a breaking format change.
* [ ] Each configuration format can be versioned independently.
* [ ] All example configuration files are updated.
* [ ] The format-version policy is documented.
* [ ] The project compiles and starts successfully with matching configuration versions.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Background
Configuration files can change in ways that are incompatible with older application versions.
This happened after changing persistent alarm grace periods from plain seconds to values with time suffixes. A new configuration containing:
was accidentally loaded by an older compiled JAR. Instead of clearly reporting an incompatible configuration format, the old parser failed with an unrelated
NumberFormatException.We need a simple and explicit way to verify that a configuration file is compatible with the parser loading it.
Proposed solution
Every configuration file format must contain a format version near the top of the file:
Blank lines and comments may appear before the declaration, but it must be the first actual configuration entry.
The corresponding parser or configuration loader must contain its supported format version as a hardcoded constant:
Before parsing any other content, the loader must compare the file version with its supported version.
The versions must match exactly. Otherwise, configuration loading and application startup must be aborted.
Independent versions
Each configuration format must have its own version number.
For example, a breaking change to
alarms.confmust not require incrementing the version ofalarmaction_Pushover.conf.The version is incremented only when a change is incompatible with the previous file format. Compatible additions do not require a new version.
When making a breaking configuration change, both of the following must be updated:
Scope
Apply format-version validation to all human-maintained runtime configuration files and their corresponding loaders.
This includes at least:
alarms.confalarmaction_Console.confalarmaction_Pushover.confalarmaction_JupiterPerpsPositionIncreaseAlarmAction.confalarmaction_JupiterPerpsPositionDecreaseAlarmAction.confevelyn.confpositions.confAll active configuration loaders must be inventoried during implementation. The scope must not be limited to classes whose names end with
ConfigurationParser, since some files may be parsed directly by another class.A shared helper may be used for reading and validating the declaration, but the supported version must remain independently defined for each configuration format.
Validation
Configuration loading must fail if:
FORMAT_VERSIONis missing.The version must be validated before the rest of the file is parsed.
Error message
A mismatch must produce a clear error containing:
Example:
Documentation and examples
FORMAT_VERSION=1to every current example configuration.Acceptance criteria
FORMAT_VERSIONdeclaration.