{"record":{"id":"7597a5b24ef49464","repo":"feder-cr/Jobs_Applier_AI_Agent_AIHawk","slug":"attribute-error-in-salary-expectations-processing","errorCode":null,"errorMessage":"Attribute error in salary_expectations processing.","messagePattern":"Attribute error in salary_expectations processing\\.","errorType":"validation","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"src/resume_schemas/job_application_profile.py","lineNumber":167,"sourceCode":"            raise AttributeError(\"Attribute error in availability processing.\") from e\n        except Exception as e:\n            logger.error(f\"An unexpected error occurred while processing availability: {e}\")\n            raise RuntimeError(\"An unexpected error occurred while processing availability.\") from e\n\n        # Process salary_expectations\n        try:\n            logger.debug(\"Processing salary_expectations\")\n            self.salary_expectations = SalaryExpectations(**data['salary_expectations'])\n            logger.debug(f\"salary_expectations processed: {self.salary_expectations}\")\n        except KeyError as e:\n            logger.error(f\"Required field {e} is missing in salary_expectations data.\")\n            raise KeyError(f\"Required field {e} is missing in salary_expectations data.\") from e\n        except TypeError as e:\n            logger.error(f\"Error in salary_expectations data: {e}\")\n            raise TypeError(f\"Error in salary_expectations data: {e}\") from e\n        except AttributeError as e:\n            logger.error(f\"Attribute error in salary_expectations processing: {e}\")\n            raise AttributeError(\"Attribute error in salary_expectations processing.\") from e\n        except Exception as e:\n            logger.error(f\"An unexpected error occurred while processing salary_expectations: {e}\")\n            raise RuntimeError(\"An unexpected error occurred while processing salary_expectations.\") from e\n\n        logger.debug(\"JobApplicationProfile initialization completed successfully.\")\n\n    def __str__(self):\n        logger.debug(\"Generating string representation of JobApplicationProfile\")\n\n        def format_dataclass(obj):\n            return \"\\n\".join(f\"{field.name}: {getattr(obj, field.name)}\" for field in obj.__dataclass_fields__.values())\n\n        formatted_str = (f\"Self Identification:\\n{format_dataclass(self.self_identification)}\\n\\n\"\n                         f\"Legal Authorization:\\n{format_dataclass(self.legal_authorization)}\\n\\n\"\n                         f\"Work Preferences:\\n{format_dataclass(self.work_preferences)}\\n\\n\"\n                         f\"Availability: {self.availability.notice_period}\\n\\n\"\n                         f\"Salary Expectations: {self.salary_expectations.salary_range_usd}\\n\\n\")\n        logger.debug(f\"String representation generated: {formatted_str}\")","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/feder-cr/Jobs_Applier_AI_Agent_AIHawk/blob/79155b52faccfbd19b834680af285eac70dd2df4/src/resume_schemas/job_application_profile.py#L149-L185","documentation":"AttributeError from the salary_expectations try block in JobApplicationProfile.__init__: an attribute/method access on a wrongly-typed nested value (None/str/int where a dict or object is expected) inside SalaryExpectations construction is caught and re-raised with this static message. The chained __cause__ and the logger.error output carry the actual attribute name.","triggerScenarios":"Nested salary fields (e.g. a range or currency object) being None or a scalar while the constructor calls .get()/.lower()/etc. on them.","commonSituations":"Sparse resumes with null salary sections; data producers with inconsistent types; refactors changing nested salary structures from scalars to objects.","solutions":["Inspect e.__cause__ or logs for the failing attribute.","Coerce None/scalar nested values to the expected shapes before constructing the profile.","Default problematic nested fields or make SalaryExpectations defensive about optional sub-objects."],"exampleFix":"# before\nse = data['salary_expectations']  # {'range': None}\nself.salary_expectations = SalaryExpectations(**se)\n\n# after\nse = {k: (v if v is not None else {}) for k, v in (data.get('salary_expectations') or {}).items()}\nself.salary_expectations = SalaryExpectations(**se)","handlingStrategy":"validation","validationCode":"se = data.get('salary_expectations') or {}\nse = {k: (v if v is not None else {}) for k, v in se.items()}","typeGuard":"def salary_fields_valid(se) -> bool:\n    return isinstance(se, dict) and all(v is None or isinstance(v, (dict, list, str, int)) for v in se.values())","tryCatchPattern":"try:\n    profile = JobApplicationProfile(**data)\nexcept AttributeError as e:\n    if 'salary_expectations' in str(e):\n        log.error('attr cause: %r', e.__cause__)","preventionTips":["Replace null nested salary fields with defaults","Keep salary structures as dicts, not bare scalars"],"tags":["python","attributeerror","null-handling","salary-expectations"],"backgroundTag":"schema-validation-failed","analyzedSha":"79155b52faccfbd19b834680af285eac70dd2df4","analyzedAt":"2026-08-28T14:10:26.659Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}