Submitting Improve always failed with status 500, details in post
Describe the bug
This is all happening when i'm running everything locally, after make setup and make run-dev, everything is working
However after I uploaded my resume and enter the job description. Pressing Improve always returns me with:
Improve failed with status 500: {"detail":"sorry, something went wrong!","request_id":"resumes:f356f24a-497e-4838-985f-107f6e44cfa2"}
This is the traceback:
[dev:backend] [2025-07-23T16:07:52+1000 - app.services.job_service - INFO] Job ID: 17494bcc-9482-422c-a453-9d73e7566d20
[dev:backend] [2025-07-23T16:08:48+1000 - app.api.router.v1.resume - ERROR] Error: 'NoneType' object has no attribute 'extracted_keywords' - traceback: Traceback (most recent call last):
[dev:backend] File "/Users/r/Development/Resume-Matcher/apps/backend/app/api/router/v1/resume.py", line 137, in score_and_improve
[dev:backend] improvements = await score_improvement_service.run(
[dev:backend] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[dev:backend] File "/Users/r/Development/Resume-Matcher/apps/backend/app/services/score_improvement_service.py", line 173, in run
[dev:backend] json.loads(processed_resume.extracted_keywords).get(
[dev:backend] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[dev:backend] AttributeError: 'NoneType' object has no attribute 'extracted_keywords'
I've also tried this with multiple different resume as well. does this mean that the resume is not AST friendly or something?
Exactly the same issue with my PDF resume. Maybe this is what's happening on the backend of the ATS for all the jobs I've applied to as well! LOL.
lolol, ~~mine is docx file but that's what I thought too~~ mine is also pdf. I thought my resume never passed the ATS screening!! @scottvr
@robertwt7 and @scottvr you're using resume.docx??
Failing for me too.
@robertwt7 and @scottvr you're using resume.docx??
No. Mine is a 69kB PDF file.
Incidentally, I tried copilot's fix-421 branch and now although I can see the text from my resume being sent to the backend and the ollama runner starting, 30 minutes later and no response from the backend. The box is CUDA and I can chat with llama3.2 in realtime, so I don't think there is an ollama issue that suddenly appeared. Just thought you might like to know; i tried to test the fix, but for some reason I can't even get to the job description page today, while the original trouble occurred after uploading the resume and being given the button to enter a job description.
actually mine is also pdf i don't know why i thought its docx :/ @srbhr , i already exported it as pdf
i haven't got a chance to look at the code or debug but i saw that backend has logged extracted_keywords so it shouldn't be None when trying to access it here processed_resume.extracted_keywords
same error message, also tried using a very simplified text version of my resume, keywords extraction looks good. installed locally linux; npm start.
After submtting any number of Job Description, clicking on "Improve" button leads to msg: Improve failed with status 500: {"detail":"sorry, something went wrong!","request_id":"resumes:4ef76463-f54f-4622-bd21-733a090b31ed"}
Also getting same error Improve failed with status 500: {"detail":"sorry, something went wrong!","request_id":"resumes:81cf981a-289a-49cb-a548-28b89d2e5149"} --- Anyone know any fixes to this?
@davidchilin @abmilo your errors don't show a lot of information. If you post the output of your PowerShell window, people are able to help you. Now it's just: "error: [random number]"
I'm getting a similar error, this is the output in my PowerShell:
[dev:backend] [2025-07-24T19:11:14+0200 - app.agent.strategies.wrapper - INFO] Saving JSON to: C:\dev\Resume-Matcher\apps\backend\raw_provider_response.json
[dev:backend] [2025-07-24T19:11:14+0200 - app.services.job_service - INFO] Job ID: (my jobID)
[dev:backend] [2025-07-24T19:11:45+0200 - app.api.router.v1.resume - ERROR] Parsing of resume with ID (my resumeID) failed.
Digging some more:
apps\backend\app\api\router\v1\resume.py shows that the error messages are loaded from app.services. In apps\backend\app\services\exceptions.py, this specific piece of code is relevant:
class ResumeParsingError(Exception):
"""
Exception raised when a resume processing and storing in the database failed.
"""
def __init__(self, resume_id: Optional[str] = None, message: Optional[str] = None):
if resume_id and not message:
message = f"Parsing of resume with ID {resume_id} failed."
elif not message:
message = "Parsed resume not found."
super().__init__(message)
self.resume_id = resume_id
I'm not sure, but it seems like the body of the message is empty (the parsed JSON is not, I have added a step that saves the json file)
Digging a bit further, I see the following function being called in score_improvement_service.py that throws the error:
async def _get_resume(
self, resume_id: str
) -> Tuple[Resume | None, ProcessedResume | None]:
"""
Fetches the resume from the database.
"""
query = select(Resume).where(Resume.resume_id == resume_id)
result = await self.db.execute(query)
resume = result.scalars().first()
if not resume:
raise ResumeNotFoundError(resume_id=resume_id)
query = select(ProcessedResume).where(ProcessedResume.resume_id == resume_id)
result = await self.db.execute(query)
processed_resume = result.scalars().first()
if not processed_resume:
raise ResumeParsingError(resume_id=resume_id)
It seems like there is no processed resume present.
In the same file (score_improvement_service.py), this is the piece of code that is causing the error, I think:
async def run(self, resume_id: str, job_id: str) -> Dict:
"""
Main method to run the scoring and improving process and return dict.
"""
resume, processed_resume = await self._get_resume(resume_id)
job, processed_job = await self._get_job(job_id)
extracted_job_keywords = ", ".join(
json.loads(processed_job.extracted_keywords).get("extracted_keywords", [])
)
extracted_resume_keywords = ", ".join(
json.loads(processed_resume.extracted_keywords).get(
"extracted_keywords", []
)
)
resume_embedding_task = asyncio.create_task(
self.embedding_manager.embed(resume.content)
)
job_kw_embedding_task = asyncio.create_task(
self.embedding_manager.embed(extracted_job_keywords)
)
resume_embedding, extracted_job_keywords_embedding = await asyncio.gather(
resume_embedding_task, job_kw_embedding_task
)
cosine_similarity_score = self.calculate_cosine_similarity(
extracted_job_keywords_embedding, resume_embedding
)
updated_resume, updated_score = await self.improve_score_with_llm(
resume=resume.content,
extracted_resume_keywords=extracted_resume_keywords,
job=job.content,
extracted_job_keywords=extracted_job_keywords,
previous_cosine_similarity_score=cosine_similarity_score,
extracted_job_keywords_embedding=extracted_job_keywords_embedding,
)
resume_preview = await self.get_resume_for_previewer(
updated_resume=updated_resume
)
logger.info(f"Resume Preview: {resume_preview}")
execution = {
"resume_id": resume_id,
"job_id": job_id,
"original_score": cosine_similarity_score,
"new_score": updated_score,
"updated_resume": markdown.markdown(text=updated_resume),
"resume_preview": resume_preview,
}
gc.collect()
return execution
Specifially:
resume, processed_resume = await self._get_resume(resume_id)
The processed_resume is taken from apps\backend\app\models\resume.py. The class ProcessedResume includes the following:
personal_data = Column(JSON, nullable=False)
experiences = Column(JSON, nullable=True)
projects = Column(JSON, nullable=True)
skills = Column(JSON, nullable=True)
research_work = Column(JSON, nullable=True)
achievements = Column(JSON, nullable=True)
education = Column(JSON, nullable=True)
extracted_keywords = Column(JSON, nullable=True)
This is the JSON that is created:
{
"UUID": "a1b2c3d4-5678-9012-3456-789012345678",
"Personal Data": {
"firstName": "(my first name)",
"lastName": "(my last name)",
"email": "(email)@gmail.,",
"phone": null,
"linkedin": null,
"portfolio": "https://www.example.com",
"location": {
"city": "(my city)",
"country": "(my country)"
}
},
Seeing as personal_data is not nullable, I think this is part of the core of the issue.
I think this is the same bug as #445, or at least the same symptoms.
Kinda having the same issue. 😥
[dev:backend] [2025-07-25T17:28:10+0200 - app.services.job_service - INFO] Validation error: 1 validation error for StructuredJobModel
[dev:backend] employmentType
[dev:backend] Input should be 'Full-time', 'Part-time', 'Contract', 'Internship', 'Temporary' or 'Not Specified' [type=enum, input_value='Permanent', input_type=str]
[dev:backend] For further information visit https://errors.pydantic.dev/2.11/v/enum
[dev:backend] [2025-07-25T17:28:10+0200 - app.services.job_service - INFO] Structured job extraction failed.
[dev:backend] [2025-07-25T17:28:10+0200 - app.services.job_service - INFO] Job ID: c43af2b1-9dad-4230-a856-dfd245d26651
[dev:backend] [2025-07-25T17:28:14+0200 - app.api.router.v1.resume - ERROR] Parsing of job with ID c43af2b1-9dad-4230-a856-dfd245d26651 failed.
You already have a clue what goes wrong: Your job description probably lists a position type "permanent" while that is not one of the keywords that RM looks for. What happens if you change it to "Full-time"?
What happens if you change it to "Full-time"?
That actually did help, it finished the job without any errors now. Thank you!
You already have a clue what goes wrong: Your job description probably lists a position type "permanent" while that is not one of the keywords that RM looks for. What happens if you change it to "Full-time"?
Thanks a lot, and it worked for me as well