{"record":{"id":"ce062c562a57cea2","repo":"mvanhorn/last30days-skill","slug":"stocktwits-stream-has-no-tagged-sentiment","errorCode":null,"errorMessage":"StockTwits stream has no tagged sentiment","messagePattern":"StockTwits stream has no tagged sentiment","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"warning","filePath":"skills/last30days/scripts/lib/stocktwits.py","lineNumber":340,"sourceCode":"        if not isinstance(data, dict) or not isinstance(data.get(\"messages\"), list):\n            raise KeyError(\"StockTwits symbol stream was not returned\")\n        batch = data[\"messages\"]\n        if not batch:\n            break\n        messages.extend(batch)\n        cursor = data.get(\"cursor\") or {}\n        if not cursor.get(\"more\") or not cursor.get(\"max\"):\n            break\n        cursor_max = cursor[\"max\"]\n    messages = _filter_by_date(\n        messages,\n        window.get(\"from_date\"),\n        window.get(\"to_date\"),\n    )\n    aggregate = aggregate_sentiment(messages)\n    value = aggregate.get(\"pct_bullish\")\n    if value is None:\n        raise KeyError(\"StockTwits stream has no tagged sentiment\")\n    newest = max(\n        (str(message.get(\"created_at\") or \"\") for message in messages),\n        default=\"\",\n    )\n    return {\n        \"value\": value,\n        \"values\": {\"pct_bullish\": value},\n        \"url\": item.url,\n        \"timestamp\": newest or None,\n    }\n\n\n# --------------------------------------------------------------------------- #\n# Standalone CLI (ad-hoc use today, before any engine wiring)                  #\n#   python3 stocktwits.py \"ServiceNow stock\"                                   #\n# --------------------------------------------------------------------------- #\nif __name__ == \"__main__\":\n    topic = \" \".join(sys.argv[1:]) or \"$NOW\"","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/mvanhorn/last30days-skill/blob/c7460f6114449ddfe6ea3fc2f23c3d910c0e740c/skills/last30days/scripts/lib/stocktwits.py#L322-L358","documentation":"KeyError raised at the end of StockTwits refetch_datum when aggregation over the (date-filtered) message stream yields no pct_bullish - meaning zero messages carry a Bullish/Bearish sentiment tag. The fetch itself succeeded; the population just has no tagged sentiment to compute a percentage from.","triggerScenarios":"refetch_datum paginates fine but every message in the window has entity sentiment or is untagged; or _filter_by_date removes all messages because the freshness window (from_date/to_date) excludes them, leaving an empty list where the bully-share is undefined.","commonSituations":"Low-volume tickers whose recent messages are mostly untagged; date windows narrowed after the original fetch so nothing remains; symbols whose traders don't use StockTwits sentiment buttons; weekends with no tagged activity.","solutions":["Catch KeyError and report 'no tagged sentiment in window' rather than an error","Widen the freshness window (from_date) or increase depth so more tagged messages are included","Pre-check the cached sample: if aggregate sample was near zero originally, skip re-verification"],"exampleFix":"# before\nval = refetch_datum(item, \"pct_bullish\")  # KeyError on untagged stream\n\n# after\ntry:\n    val = refetch_datum(item, \"pct_bullish\")\nexcept KeyError:\n    val = {\"value\": None, \"note\": \"no tagged sentiment in freshness window\"}","handlingStrategy":"fallback","validationCode":"window = item.metadata.get(\"freshness_window\") or {}\nif window.get(\"from_date\") and days_between(window[\"from_date\"], today()) > 30:\n    skip_refetch(item)  # window too narrow to expect tagged messages","typeGuard":null,"tryCatchPattern":"try:\n    datum = refetch_datum(item, \"pct_bullish\")\nexcept KeyError as e:\n    if \"no tagged sentiment\" in str(e):\n        datum = {\"value\": None, \"note\": \"no tagged sentiment in window\"}","preventionTips":["Widen from_date or bump depth when the original sample of tagged messages was tiny","Skip re-verification for low-volume symbols known not to use sentiment tags","Treat 'no data in window' as a valid empty result, not a failure"],"tags":["stocktwits","sentiment","keyerror","empty-data"],"backgroundTag":null,"analyzedSha":"c7460f6114449ddfe6ea3fc2f23c3d910c0e740c","analyzedAt":"2026-08-15T03:34:49.540Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}