{"record":{"id":"6f640aa7cdaad726","repo":"oraios/serena","slug":"gopls-settings-must-be-a-dict-got-type-gopls-set","errorCode":null,"errorMessage":"gopls_settings must be a dict, got {type(gopls_settings).__name__}. Expected structure: {'buildFlags': ['-tags=foo'], 'env': {...}, ...}","messagePattern":"gopls_settings must be a dict, got (.+?)\\. Expected structure: (.+?), \\.\\.\\.\\}","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/solidlsp/language_servers/gopls.py","lineNumber":151,"sourceCode":"        # Serena applies gopls settings at initialization time via initializationOptions\n        # (Access settings directly to avoid extra INFO logging from CustomLSSettings.get.)\n        gopls_settings = self._custom_settings.settings.get(\"gopls_settings\")\n        if gopls_settings:\n            gopls_settings = self._validate_gopls_settings_dict(gopls_settings)\n\n            # Validate JSON-serializability early: initializationOptions is sent over JSON-RPC.\n            import json\n\n            self._canonical_json_or_raise(json, gopls_settings)\n\n            # Log keys only (and at DEBUG) to avoid leaking sensitive values and to reduce startup noise.\n            log.debug(\"Applying gopls settings via initializationOptions: keys=%s\", list(gopls_settings.keys()))\n            initialize_params[\"initializationOptions\"] = gopls_settings\n\n        return initialize_params\n\n    def _validate_gopls_settings_dict(self, gopls_settings: object) -> dict:\n        if not isinstance(gopls_settings, dict):\n            raise TypeError(\n                f\"gopls_settings must be a dict, got {type(gopls_settings).__name__}. \"\n                \"Expected structure: {'buildFlags': ['-tags=foo'], 'env': {...}, ...}\"\n            )\n\n        return gopls_settings\n\n    def _canonical_json_or_raise(self, json_module: Any, data: object) -> str:\n        try:\n            return json_module.dumps(data, sort_keys=True, separators=(\",\", \":\"))\n        except (TypeError, ValueError) as exc:\n            raise TypeError(\n                \"gopls_settings must be JSON-serializable (json.dumps). Use JSON-compatible values (dict/list/str/int/float/bool/null) and prefer string keys.\"\n            ) from exc\n\n    # Environment variables that influence Go build context and affect cached symbols.\n    _CACHE_CONTEXT_ENV_KEYS = (\"GOFLAGS\", \"GOOS\", \"GOARCH\", \"CGO_ENABLED\")\n","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/solidlsp/language_servers/gopls.py#L133-L169","documentation":"TypeError raised by Gopls._validate_gopls_settings_dict when the user-supplied gopls_settings value is not a dict. The settings are forwarded verbatim as LSP initializationOptions, so anything other than a mapping is invalid. Called from _create_base_initialize_params and _raw_document_symbols_cache_fingerprint.","triggerScenarios":"Passing gopls_settings as a string (e.g. JSON text), list, None, or a non-dict object when creating the Gopls server or computing the document-symbols cache fingerprint.","commonSituations":"Loading settings from a YAML/JSON config file that yields a string instead of a parsed dict; passing a JSON-encoded string where an object was expected; mixing up positional/keyword arguments.","solutions":["Parse the settings into a dict before passing them (json.loads for JSON text)","Pass settings as a keyword argument: gopls_settings={'buildFlags': [...], 'env': {...}}","Check the config file section that supplies the settings — ensure it is a mapping, not a scalar","If defaults are acceptable, omit gopls_settings entirely rather than passing None or an empty string"],"exampleFix":"// before\nserver = Gopls(..., gopls_settings='{\"buildFlags\": []}')  # JSON string\n// after\nimport json\nraw = '{\"buildFlags\": []}'\nserver = Gopls(..., gopls_settings=json.loads(raw))","handlingStrategy":"type-guard","validationCode":"def validate_gopls_settings(settings):\n    if settings is not None and not isinstance(settings, dict):\n        raise TypeError(f'gopls_settings must be dict, got {type(settings).__name__}')","typeGuard":"def is_gopls_settings(value) -> bool:\n    return isinstance(value, dict) and all(isinstance(k, str) for k in value)\n\n# usage\nif not is_gopls_settings(cfg.get('gopls_settings')):\n    raise ValueError('gopls_settings must be a dict with string keys')","tryCatchPattern":"try:\n    server = Gopls(..., gopls_settings=user_settings)\nexcept TypeError as e:\n    if 'gopls_settings must be a dict' in str(e):\n        log.error('Fix configuration: gopls_settings must be a mapping')\n        raise","preventionTips":["Parse JSON/YAML config into dicts before passing (json.loads, yaml.safe_load)","Pass gopls_settings as an explicit keyword argument","Add a startup assertion validating settings type in your integration tests","Never pass JSON-encoded strings where dicts are expected"],"tags":["gopls","validation","type-error","configuration"],"backgroundTag":"invalid-settings-type","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}