{"record":{"id":"cdb2469db6cc26b8","repo":"trailofbits/algo","slug":"error-while-checking-if-attributes-should-be-chang","errorCode":null,"errorMessage":"Error while checking if attributes should be changed","messagePattern":"Error while checking if attributes should be changed","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"library/scaleway_compute.py","lineNumber":586,"sourceCode":"    )\n    compute_api.module.debug(\"Debug dict %s\" % debug_dict)\n    try:\n        for key in PATCH_MUTABLE_SERVER_ATTRIBUTES:\n            if key in target_server and key in wished_server:\n                # When you are working with dict, only ID matter as we ask user to put only the resource ID in the playbook\n                if (\n                    isinstance(target_server[key], dict)\n                    and wished_server[key]\n                    and \"id\" in target_server[key].keys()\n                    and target_server[key][\"id\"] != wished_server[key]\n                ):\n                    return True\n                # Handling other structure compare simply the two objects content\n                elif not isinstance(target_server[key], dict) and target_server[key] != wished_server[key]:\n                    return True\n        return False\n    except AttributeError:\n        compute_api.module.fail_json(msg=\"Error while checking if attributes should be changed\")\n\n\ndef server_change_attributes(compute_api, target_server, wished_server):\n    compute_api.module.debug(\"Starting patching server attributes\")\n    patch_payload = dict()\n\n    for key in PATCH_MUTABLE_SERVER_ATTRIBUTES:\n        if key in target_server and key in wished_server:\n            # When you are working with dict, only ID matter as we ask user to put only the resource ID in the playbook\n            if isinstance(target_server[key], dict) and \"id\" in target_server[key] and wished_server[key]:\n                # Setting all key to current value except ID\n                key_dict = dict((x, target_server[key][x]) for x in target_server[key].keys() if x != \"id\")\n                # Setting ID to the user specified ID\n                key_dict[\"id\"] = wished_server[key]\n                patch_payload[key] = key_dict\n            elif not isinstance(target_server[key], dict):\n                patch_payload[key] = wished_server[key]\n","sourceCodeStart":568,"sourceCodeEnd":604,"githubUrl":"https://github.com/trailofbits/algo/blob/20e22a8715c198b38c01c1ca62d0953b93587a74/library/scaleway_compute.py#L568-L604","documentation":"This error is raised when comparing the target server's current attributes against the wished (desired) configuration raises an AttributeError — typically because an expected key is missing from the API-returned server dict (target_server[key] or a nested dict attribute access fails) or a value is None where a dict was assumed.","triggerScenarios":"server_attributes_should_be_changed iterates over wished_server keys and accesses target_server[key] / .get(...); if the fetched server JSON lacks an attribute (API version differences, stopped/archived servers omitting fields like 'image' or 'public_ip'), the attribute access throws AttributeError.","commonSituations":"Scaleway API responses changed shape between API versions, comparing against a server in 'stopped'/'archived' state that omits fields, or passing a malformed wished_server dict to the module.","solutions":["Print/dump target_server and wished_server to find the missing key (add a debug task)","Update the module's attribute comparison to use target_server.get(key) instead of direct indexing","Pin to a known-good Scaleway API/module version if the response schema changed","Ensure the server exists and is fully provisioned before running attribute changes"],"exampleFix":"// before\nelif not isinstance(target_server[key], dict) and target_server[key] != wished_server[key]:\n// after\nelif not isinstance(target_server.get(key), dict) and target_server.get(key) != wished_server.get(key):","handlingStrategy":"validation","validationCode":"# Verify required keys exist before comparing\nmissing = [k for k in wished if k not in (target or {})]\nassert not missing, f'API response missing keys: {missing}'","typeGuard":"def has_keys(d: dict, keys: list[str]) -> bool:\n    return isinstance(d, dict) and all(k in d for k in keys)","tryCatchPattern":null,"preventionTips":["Pin module and API versions together","Use .get() when reading optional API fields"],"tags":["scaleway","ansible","attribute-error","api-schema"],"backgroundTag":"dict-key-missing","analyzedSha":"20e22a8715c198b38c01c1ca62d0953b93587a74","analyzedAt":"2026-08-28T13:26:02.752Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}