{"record":{"id":"2a316ae1c604843a","repo":"ZhuLinsen/daily_stock_analysis","slug":"invalid-share-image-record-id","errorCode":null,"errorMessage":"Invalid share image record ID","messagePattern":"Invalid share image record ID","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"apps/dsa-desktop/main.js","lineNumber":1347,"sourceCode":"  }, 3000);\n\n  return waitAndClear();\n}\n\nfunction resolveDesktopVersion() {\n  return String(app.getVersion() || '').trim();\n}\n\nfunction buildMainPageUrl(port, timestamp = Date.now(), host = DESKTOP_BACKEND_DEFAULT_HOST) {\n  const url = new URL(buildBackendUrl(host, port, '/'));\n  url.searchParams.set('desktop_version', resolveDesktopVersion() || 'unknown');\n  url.searchParams.set('cache_bust', String(timestamp));\n  return url.toString();\n}\n\nfunction buildDesktopShareImageUrl(pageUrl, recordId, expectedBackendOrigin = '') {\n  if (!Number.isSafeInteger(recordId) || recordId <= 0) {\n    throw new Error('Invalid share image record ID');\n  }\n\n  let page;\n  try {\n    page = new URL(pageUrl);\n  } catch (_error) {\n    throw new Error('Desktop backend URL is unavailable');\n  }\n\n  let expectedOrigin = page.origin;\n  if (expectedBackendOrigin) {\n    try {\n      expectedOrigin = new URL(expectedBackendOrigin).origin;\n    } catch (_error) {\n      throw new Error('Desktop backend origin is invalid');\n    }\n  }\n  if (page.protocol !== 'http:' || !page.port || page.origin !== expectedOrigin) {","sourceCodeStart":1329,"sourceCodeEnd":1365,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/apps/dsa-desktop/main.js#L1329-L1365","documentation":"Raised by PortfolioService.query_trades when both date_from and date_to are supplied and date_from is strictly later than date_to. It is a request-contract check executed before the repository query, so no SQL runs; the API layer maps it to code=validation_error.","triggerScenarios":"GET /portfolio/trades?date_from=2025-06-30&date_to=2025-01-01, or the equivalent Python call query_trades(date_from=date(2025,6,30), date_to=date(2025,1,1)). Equal dates are allowed; only a strictly greater date_from raises.","commonSituations":"UI date-range pickers that let users pick an inverted range; timezone shifts that flip a 'last 7 days' calculation; copy-paste of date strings where from/to fields are swapped; programmatic ranges built from max/min in the wrong order.","solutions":["Swap the two dates when date_from > date_to before submitting the query","Fix the range-builder in the caller (e.g. use min(start,end)/max(start,end))","Validate the range client-side in the Web/Desktop UI and disable submit when inverted","If dates derive from timestamps, convert to dates in a single timezone before comparing"],"exampleFix":"# before\nsvc.query_trades(date_from=end_date, date_to=start_date)\n# after\nsvc.query_trades(date_from=min(start_date, end_date), date_to=max(start_date, end_date))","handlingStrategy":"validation","validationCode":"def safe_range(date_from, date_to):\n    if date_from and date_to and date_from > date_to:\n        date_from, date_to = date_to, date_from\n    return date_from, date_to","typeGuard":"from datetime import date\n\ndef is_valid_date_range(d_from: date | None, d_to: date | None) -> bool:\n    return d_from is None or d_to is None or d_from <= d_to","tryCatchPattern":"try:\n    svc.query_trades(date_from=f, date_to=t)\nexcept ValueError as exc:\n    if \"date_from must be <= date_to\" in str(exc):\n        f, t = t, f  # or reject the request\n        svc.query_trades(date_from=f, date_to=t)\n    else:\n        raise","preventionTips":["Always construct ranges as (min(start,end), max(start,end))","Block inverted ranges in date-picker UIs","Convert timestamps to dates in one timezone before comparing"],"tags":["portfolio","validation","date-range","query"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}