feder-cr/Jobs_Applier_AI_Agent_AIHawk · error · TypeError
Invalid data for Education: {e}
Error message
Invalid data for Education: {e} What it means
EducationDetails construction failed with a TypeError — wrong-typed or unexpected keyword arguments. Common causes: exam entries built via Exam(name=k, grade=v) where v isn't a str, a required field missing from the kwargs (Python reports missing arguments as TypeError), or extra keys passed through.
Source
Thrown at src/resume_schemas/resume.py:153
def _process_education_details(self, data: List[Dict[str, Any]]) -> List[EducationDetails]:
education_list = []
for edu in data:
try:
exams = [Exam(name=k, grade=v) for k, v in edu.get('exam', {}).items()]
education = EducationDetails(
education_level=edu.get('education_level'),
institution=edu.get('institution'),
field_of_study=edu.get('field_of_study'),
final_evaluation_grade=edu.get('final_evaluation_grade'),
start_date=edu.get('start_date'),
year_of_completion=edu.get('year_of_completion'),
exam=exams
)
education_list.append(education)
except KeyError as e:
raise KeyError(f"Missing field in education details: {e}") from e
except TypeError as e:
raise TypeError(f"Invalid data for Education: {e}") from e
except AttributeError as e:
raise AttributeError(f"AttributeError in Education: {e}") from e
except Exception as e:
raise Exception(f"Unexpected error in Education processing: {e}") from e
return education_list
def _process_experience_details(self, data: List[Dict[str, Any]]) -> List[ExperienceDetails]:
experience_list = []
for exp in data:
try:
key_responsibilities = [
Responsibility(description=list(resp.values())[0])
for resp in exp.get('key_responsibilities', [])
]
skills_acquired = [str(skill) for skill in exp.get('skills_acquired', [])]
experience = ExperienceDetails(
position=exp['position'],
company=exp['company'],View on GitHub (pinned to 79155b52fa)
Solutions
- Check the TypeError text: 'missing 1 required positional argument' vs 'unexpected keyword argument' pinpoints the field.
- Normalize the exam structure before the loop: if isinstance(edu.get('exam'), list): convert to a dict.
- Add defaults (Optional[...] = None) to non-critical EducationDetails fields.
- Validate types of values (grade must be str/int) before constructing Exam.
Example fix
// before
exams = [Exam(name=k, grade=v) for k, v in edu.get('exam', {}).items()]
# after
exam_data = edu.get('exam') or {}
if not isinstance(exam_data, dict):
exam_data = {e['name']: e['grade'] for e in exam_data}
exams = [Exam(name=k, grade=str(v)) for k, v in exam_data.items()] Defensive patterns
Strategy: type-guard
Validate before calling
exam = edu.get('exam') or {}
if not isinstance(exam, dict):
if isinstance(exam, list):
exam = {item['name']: item['grade'] for item in exam if isinstance(item, dict)}
else:
exam = {} Type guard
def is_exam_map(x: Any) -> TypeGuard[dict]:
return isinstance(x, dict) and all(isinstance(v, (str, int, float)) for v in x.values()) Try / catch
try:
edu_list = _process_education_details(data)
except TypeError as e:
logger.error("education type mismatch: %s", e)
raise Prevention
- Normalize 'exam' shape (dict vs list) before iterating .items()
- Coerce grades to str when building Exam
- Prefer .get() over [] for optional fields
When it happens
Trigger: edu.get('exam', {}) returning a non-dict (e.g. a list) so .items() yields malformed k/v; EducationDetails called without a required argument because a .get() returned None where the field has no default.
Common situations: LLM-generated resumes where 'exam' is sometimes a list of objects instead of a {name: grade} map; schema drift adding new required fields.
Related errors
- Invalid data for PersonalInformation: {e}
- Invalid data for Experience: {e}
- Error in self_identification data: {e}
- Attribute error in self_identification processing.
- Error in legal_authorization data: {e}
AI-assisted analysis of feder-cr/Jobs_Applier_AI_Agent_AIHawk@79155b52fa (2026-08-28).
Data as JSON: /api/errors/df748265b13a9bbc.
Report an issue: GitHub.