{"record":{"id":"baea67af657f1179","repo":"affaan-m/ECC","slug":"built-an-invalid-spec-problems","errorCode":null,"errorMessage":"built an invalid spec: {problems}","messagePattern":"built an invalid spec: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/distill.py","lineNumber":77,"sourceCode":"    \"\"\"Assemble a schema-valid spec from look constraints (offline).\"\"\"\n    spec: dict[str, Any] = {}\n    for key in _SPEC_STRING_KEYS:\n        value = look.get(key)\n        spec[key] = value.strip() if isinstance(value, str) else \"\"\n    for key in _SPEC_LIST_KEYS:\n        value = look.get(key)\n        spec[key] = [str(v) for v in value] if isinstance(value, list) else []\n\n    spec[\"source\"] = {\n        \"pack\": pack_name or \"\",\n        \"generated\": _utc_now(),\n        \"dry_run\": True,\n        \"provider\": \"none\",\n        \"grounding_used\": grounding_used,\n    }\n    problems = schema.validate(spec, schema.SPEC_SCHEMA)\n    if problems:\n        raise ValueError(f\"built an invalid spec: {problems}\")\n    return spec\n\n\ndef distill_local(profile: dict[str, Any],\n                  sp: pack_mod.StylePack | None = None) -> dict[str, Any]:\n    \"\"\"Deterministic offline distillation of a taste profile.\n\n    The output carries dry-run semantics from the recovered implementation:\n    ``dry_run: true`` and ``provider: none`` mean no vision model ran and no\n    claim of live distillation is made. When a pack with grade/cadence\n    metadata is supplied, its measured ground truth is embedded for the\n    operator (and any future authorized VLM call) to consume.\n    \"\"\"\n    look = dict(profile.get(\"constraints\", {}).get(\"look\", {}))\n\n    grounding_used = False\n    grounding_text = \"\"\n    if sp is not None:","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/distill.py#L59-L95","documentation":"build_spec constructs a taste-distillation spec and validates it against SPEC_SCHEMA before returning it. If the assembled spec fails schema validation, it raises ValueError with the list of schema problems. This is an internal invariant check: the builder itself produced something invalid, indicating a bug or bad profile data feeding it.","triggerScenarios":"Calling build_spec (via distill_local) with profile/pack data that causes an invalid field — e.g. wrong types in the taste profile, a missing required key the builder copies through, or a modified SPEC_SCHEMA that the builder no longer satisfies.","commonSituations":"Upstream profile JSON with unexpected shapes (string numbers, null fields), locally edited schemas or builder code drifting apart, or passing a StylePack of the wrong shape.","solutions":["Read the `problems` list in the message — it names the exact failing field and reason","Validate the input profile against the expected profile schema before calling distill_local/build_spec","Fix the offending field in the profile (types/enums/required keys) per the problems output","If you edited SPEC_SCHEMA or build_spec locally, revert them to a consistent pair"],"exampleFix":"// before: profile with bad field\n{\"budget\": \"cheap\"}  # schema expects number\n// after\n{\"budget\": 3.0}\n# then: distill_local(profile)","handlingStrategy":"try-catch","validationCode":"from tasteforge.distill import schema\ndef profile_buildable(profile: dict) -> bool:\n    try:\n        spec = build_spec(profile)\n        return schema.validate(spec, schema.SPEC_SCHEMA) == []\n    except ValueError:\n        return False","typeGuard":"def is_valid_profile(p) -> bool:\n    return isinstance(p, dict) and all(isinstance(v, (str, int, float, bool, type(None))) for v in p.values())","tryCatchPattern":"try:\n    spec = build_spec(profile)\nexcept ValueError as e:\n    print(e)  # message lists exact schema problems; fix profile fields accordingly\n    spec = None","preventionTips":["Validate taste profiles against the profile schema before distillation","Avoid local edits that desynchronize build_spec and SPEC_SCHEMA","Parse profile JSON strictly so numbers stay numbers and nulls are explicit"],"tags":["schema","validation","spec","internal"],"backgroundTag":"schema-validation-failed","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}