Skip to main content

Command Palette

Search for a command to run...

When Your Frontend Hits an API That Doesn't Exist — Debugging 405 Method Not Allowed

Published
2 min read

Got a bug report: renaming a project returns 405 Method Not Allowed on a self-built dashboard. The cause was simple, but it's a classic gotcha when maintaining SPAs long-term.

Symptoms

Inline-editing a project name triggers POST /api/simple-tasks/rename 405 (METHOD NOT ALLOWED) in the browser console. Flask's server log showed the same 405.

Root Cause: Frontend-Backend Route Mismatch

Flask had /api/update-project-name registered in a different context, but the frontend JavaScript was calling /api/simple-tasks/rename.

  • The frontend (SPA) was written to use a new API path
  • The backend (Flask) never got the corresponding route added

Flask returns 405 because it doesn't know the path. When another route with the same prefix exists, Flask's routing can interpret it as path matches but method doesn't — hence 405 instead of 404.

The Fix

Added the corresponding endpoint near the existing simple-tasks routes:

@app.route('/api/simple-tasks/rename', methods=['POST'])
def simple_tasks_rename():
    data = request.get_json()
    project_id = data.get('project')
    new_name = data.get('name')

    if not project_id or not new_name:
        return jsonify({'error': 'project and name required'}), 400

    tasks_data = load_simple_tasks()
    for proj in tasks_data.get('projects', []):
        if proj['id'] == project_id:
            proj['name'] = new_name
            break
    else:
        return jsonify({'error': 'project not found'}), 404

    save_simple_tasks(tasks_data)
    return jsonify({'ok': True})

The Trap: Zombie Processes

After writing the fix and restarting Flask, the 405 persisted. The old Flask process was still holding the port. systemctl restart failed to properly kill it.

fuser -k <PORT>/tcp
systemctl --user start task-dashboard.service

Prevention

  1. Maintain an API route inventory in your README
  2. Grep frontend fetch calls periodically and cross-reference against backend routes
  3. Print routes on startup using Flask's app.url_map
  4. Watch for zombie processes — when a fix doesn't take effect, check the port with fuser / lsof -i

Conclusion

405 means either route doesn't exist or wrong method. When growing a custom API alongside an SPA, route mismatches are inevitable. Maintain an API inventory and update both sides simultaneously. And when your fix doesn't take effect — check fuser first.

More from this blog

A

techsfree

208 posts