ZhuLinsen/daily_stock_analysis · error · Error
请提供文件或粘贴文本
Error message
请提供文件或粘贴文本
What it means
Raised during full account replay (_replay_account, portfolio_service.py:819) when a cash event's direction is neither 'in' nor 'out'. The replay must decide whether to add or subtract the amount; an unknown direction aborts the entire snapshot computation with validation_error.
Source
Thrown at apps/dsa-web/src/api/stocks.ts:52
rawText: data.raw_text,
};
},
async parseImport(file?: File, text?: string): Promise<ExtractFromImageResponse> {
if (file) {
const formData = new FormData();
formData.append('file', file);
const headers: { [key: string]: string | undefined } = { 'Content-Type': undefined };
const response = await apiClient.post('/api/v1/stocks/parse-import', formData, { headers });
const data = response.data as { codes?: string[]; items?: ExtractItem[] };
return { codes: data.codes ?? [], items: data.items };
}
if (text) {
const response = await apiClient.post('/api/v1/stocks/parse-import', { text });
const data = response.data as { codes?: string[]; items?: ExtractItem[] };
return { codes: data.codes ?? [], items: data.items };
}
throw new Error('请提供文件或粘贴文本');
},
};
View on GitHub (pinned to 5159bd72e8)
Solutions
- Query cash_events for the account where direction IS NULL or NOT IN ('in','out') and repair the rows
- Normalize legacy rows: UPDATE cash_events SET direction = LOWER(TRIM(direction)) and map synonyms to in/out
- Route all new writes through add_cash_event, which validates against VALID_CASH_DIRECTIONS
- Add an audit query after bulk imports
Example fix
# before raw_insert(direction="DEPOSIT", amount=1000.0) # after svc.add_cash_event(account_id=1, direction="in", amount=1000.0, event_date=d, ...)
Defensive patterns
Strategy: validation
Validate before calling
VALID_CASH_DIRECTIONS = {"in", "out"}
def stored_direction_ok(direction):
return bool(direction) and direction.strip().lower() in VALID_CASH_DIRECTIONS Type guard
from typing import Literal, TypeGuard
StoredCashDirection = Literal["in", "out"]
def is_stored_cash_direction(value: str | None) -> TypeGuard[StoredCashDirection]:
return bool(value) and value.strip().lower() in {"in", "out"} Try / catch
try:
svc.get_snapshot(account_id=a)
except ValueError as exc:
if "Unsupported cash direction" in str(exc):
normalize_cash_directions_in_db(a); svc.get_snapshot(account_id=a)
else:
raise Prevention
- Note the replay compares direction exactly ('in'/'out', lowercase)
- Write cash events only via add_cash_event
- Normalize legacy uppercase/synonym rows during migration
When it happens
Trigger: A cash_events row with direction='IN ' with trailing characters that break the exact match (note: unlike the query path, this check is exact, not lowercased), direction='deposit', direction=NULL, or any non-enum value written outside add_cash_event's validated path.
Common situations: Direct DB inserts from migration scripts using debit/credit vocabulary; importer defaulting missing direction to NULL; a legacy writer that stored 'IN'/'OUT' uppercase before normalization was added at the write boundary — this replay branch compares event.direction == 'in' exactly.
Related errors
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/cf9449cbceee2f4c.
Report an issue: GitHub.