microsoft/qlib · error · ValueError
generate_portfolio_metrics should be True if you want to gen
Error message
generate_portfolio_metrics should be True if you want to generate portfolio_metrics
What it means
DiskDatasetCache._dataset_uri (qlib/data/cache.py:762) raises the same inst_processor guard as _dataset: with disk_cache != 0 and non-empty inst_processors, qlib cannot serve a shared dataset-cache URI whose contents would depend on the per-instrument processors. The fix set is identical — disk_cache=0 (client-side load path, which only walks expression caches) or no dataset cache.
Source
Thrown at qlib/backtest/account.py:413
trade_start_time=trade_start_time,
trade_exchange=trade_exchange,
atomic=atomic,
outer_trade_decision=outer_trade_decision,
trade_info=trade_info,
inner_order_indicators=inner_order_indicators,
decision_list=decision_list,
indicator_config=indicator_config,
)
def get_portfolio_metrics(self) -> Tuple[pd.DataFrame, dict]:
"""get the history portfolio_metrics and positions instance"""
if self.is_port_metr_enabled():
assert self.portfolio_metrics is not None
_portfolio_metrics = self.portfolio_metrics.generate_portfolio_metrics_dataframe()
_positions = self.get_hist_positions()
return _portfolio_metrics, _positions
else:
raise ValueError("generate_portfolio_metrics should be True if you want to generate portfolio_metrics")
def get_trade_indicator(self) -> Indicator:
"""get the trade indicator instance, which has pa/pos/ffr info."""
return self.indicator
View on GitHub (pinned to 79633dd950)
Solutions
- Pass disk_cache=0 in D.features so the server only checks expression caches and the client applies inst_processors itself
- Run qlib.init(dataset_cache=None) to remove the dataset cache from the provider chain
- Move instrument-level processing out of the data layer into dataset processors (DataHandlerLP)
Example fix
# before uri = D.features(insts, fields, start, end, disk_cache=1, inst_processors=[p]) # ValueError # after uri = D.features(insts, fields, start, end, disk_cache=0, inst_processors=[p])
Defensive patterns
Strategy: validation
Validate before calling
assert not (inst_processors and disk_cache), \
"inst_processors require disk_cache=0 with a configured dataset cache" Type guard
def safe_disk_cache(disk_cache: int, inst_processors) -> int:
return 0 if inst_processors else disk_cache Try / catch
try:
uri = cache.dataset(insts, fields, start, end, disk_cache=1, inst_processors=procs, return_uri=True)
except ValueError as e:
if "does not support inst_processor" in str(e):
uri = cache.dataset(insts, fields, start, end, disk_cache=0, inst_processors=procs, return_uri=True)
else:
raise Prevention
- In client/server deployments, encode the disk_cache=0 rule whenever processors are configured
- Centralize D.features calls behind one wrapper that enforces the compatibility rule
- Document which pipelines use inst_processors so cache config stays consistent
When it happens
Trigger: Requesting a dataset cache URI (D.features with disk_cache=1 in client/server mode, or DatasetCache.dataset with return_uri semantics) while passing inst_processors; the disk_cache=0 branch above it returns "" after multi_cache_walker, but any other value plus processors triggers the ValueError.
Common situations: Client/server qlib deployments combining instrument processors with dataset-cache serving; switching a pipeline to inst_processors without changing the disk_cache flag.
Related errors
- This type of input is not supported
- inner_order_indicators is necessary in un-atomic executor
- account must be in (int, float, dict)
- Invalid mount path
- Unknown mount error: {error_output.strip()}
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/ab3696a0a64b954f.
Report an issue: GitHub.