Skip to content

CLI flags silently overridden by config file for 13 parameters #6567

@vividctrlalt

Description

@vividctrlalt

Software Versions

Version : develop branch (commit 13b68eac0)

Expected behaviour

CLI flags should take priority over config file values. This is the standard convention (CLI > config file > default) and is already correctly implemented for 9 other parameters (e.g. --storage-db-directory, --trust-node) using the Optional pattern.

java -jar FullNode.jar --rpc-thread 16
# Expected: rpcThreadNum = 16

Actual behaviour

For 13 parameters, Args.setParam(Config) unconditionally overwrites the CLI value with the config file value. The CLI flags are silently ignored.

# config.conf contains: node.rpc.thread = 8
java -jar FullNode.jar --rpc-thread 16
# Actual: rpcThreadNum = 8 (CLI value lost)

Root cause — unconditional assignment in Args.setParam():

PARAMETER.rpcThreadNum = config.hasPath(ConfigKey.NODE_RPC_THREAD)
    ? config.getInt(ConfigKey.NODE_RPC_THREAD)
    : Runtime.getRuntime().availableProcessors() / 2;
// JCommander-set value of 16 is overwritten to 8

Frequency

100% — every time a config file key exists for any of the 13 affected parameters.

Steps to reproduce the behaviour

  1. Set node.rpc.thread = 8 in config.conf
  2. Start node with java -jar FullNode.jar -c config.conf --rpc-thread 16
  3. Observe that rpcThreadNum is 8, not 16

Any of the following 13 parameters can reproduce the same issue:

# CLI Flag Field Config Key
1 --support-constant supportConstant vm.supportConstant
2 --max-energy-limit-for-constant maxEnergyLimitForConstant vm.maxEnergyLimitForConstant
3 --lru-cache-size lruCacheSize vm.lruCacheSize
4 --min-time-ratio minTimeRatio vm.minTimeRatio
5 --max-time-ratio maxTimeRatio vm.maxTimeRatio
6 --long-running-time longRunningTime vm.longRunningTime
7 --save-internaltx saveInternalTx vm.saveInternalTx
8 --save-featured-internaltx saveFeaturedInternalTx vm.saveFeaturedInternalTx
9 --max-connect-number maxHttpConnectNumber node.maxHttpConnectNumber
10 --rpc-thread rpcThreadNum node.rpc.thread
11 --solidity-thread solidityThreads node.solidity.threads
12 --validate-sign-thread validateSignThreadNum node.validateSignThreadNum
13 --history-balance-lookup historyBalanceLookup storage.balance.history.lookup

Backtrace

Not applicable — no crash or exception. The bug is silent incorrect behavior.


Below is the full findings of all 34 @Parameter CLI flags in CommonParameter and additional findings.

full findings: all 34 CLI parameters by category

Category 1: Startup parameters (6) — No issue

Only control startup flow, no config file overlap.

CLI Flag Field Description
-c, --config shellConfFileName Config file path
-d, --output-directory outputDirectory Data directory
--log-config logbackPath Log config file
-h, --help help Print help and exit
-v, --version version Print version and exit
--password password Witness password

Category 2: CLI-only parameters (10) — No issue

Only set by CLI, setParam(Config) does not override.

CLI Flag Field Description
-w, --witness witness Witness mode
-p, --private-key privateKey Witness private key
--witness-address witnessAddress Witness address
--debug debug TVM debug mode
--fast-forward fastForward Fast forward mode
--solidity solidityNode Solidity node mode
--keystore-factory keystoreFactory KeystoreFactory mode
--p2p-disable p2pDisable Disable P2P module
--es eventSubscribe Enable event subscription
--contract-parse-enable contractParseEnable Contract parse switch

Category 3: CLI + Config, CLI priority (9) — Correct

Uses Optional pattern, CLI value takes priority when present.

CLI Flag Field Config Key
--storage-db-directory storageDbDirectory storage.db.directory
--storage-db-engine storageDbEngine storage.db.engine
--storage-db-synchronous storageDbSynchronous storage.db.synchronous
--storage-index-directory storageIndexDirectory storage.index.directory
--storage-index-switch storageIndexSwitch storage.index.switch
--storage-transactionHistory-switch storageTransactionHistorySwitch storage.transactionHistory.switch
--trust-node trustNodeAddr node.trustNode
--save-cancel-all-unfreeze-v2-details saveCancelAllUnfreezeV2Details vm.saveCancelAllUnfreezeV2Details
--seed-nodes seedNodes seed.node.ip.list

Category 4: CLI + Config, config overwrites CLI (13) — BUG

See "Steps to reproduce" section above for full list.

Other issues found during investigation

clearParam() misses 9 fields

clearParam() is used for test state reset, but the following fields are not cleared, which may cause test pollution:

  • maxEnergyLimitForConstant, lruCacheSize
  • allowDelegateOptimization, unfreezeDelayDays
  • allowDynamicEnergy, dynamicEnergyThreshold, dynamicEnergyIncreaseFactor, dynamicEnergyMaxFactor
  • saveCancelAllUnfreezeV2Details

Inconsistent default value patterns

Two patterns coexist in Args.setParam():

  • Pattern A (ternary): default value explicit — config.hasPath(key) ? config.get(key) : defaultValue
  • Pattern B (if-block, no else): default value hidden in CommonParameter field declaration

Mixing both increases maintenance burden. Suggest unifying to Pattern A.

CommonParameter overloaded

780 lines, ~150 fields, mixing CLI parameters, config file values, and runtime objects. Long-term suggestion: split into domain-specific classes (RpcConfig, StorageConfig, VmConfig, etc.).

Suggested improvement roadmap

Industry comparison

Project CLI/Config Overlap Strategy Priority Rule
Nginx Nearly none CLI for startup ops only; all business config in file CLI > config
Hadoop Full overlap All items overridable via -D key=value; multi-layer XML merge CLI > site XML > default XML
Kubernetes Heavy → deprecating CLI Migrating to config file; CLI flags marked deprecated CLI > config file

java-tron's current situation is most similar to early Kubernetes.

Short-term (current release): Fix the priority bug

if (PARAMETER.rpcThreadNum <= 0) {
    PARAMETER.rpcThreadNum = config.hasPath(ConfigKey.NODE_RPC_THREAD)
        ? config.getInt(ConfigKey.NODE_RPC_THREAD)
        : Runtime.getRuntime().availableProcessors() / 2;
}

Mid-term (next release): Deprecate overlapping CLI flags

@Deprecated  // Use node.rpc.thread in config.conf instead
@Parameter(names = {"--rpc-thread"}, description = "[DEPRECATED] Num of gRPC thread")
public int rpcThreadNum;

Long-term (future release): Converge to Nginx model

Only keep ~8 startup-class CLI parameters (-c, -d, -w, -p, -h, -v, --password, --log-config). All other runtime parameters managed exclusively by config file.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions