Exception Nostalgia!! Coded in Java for several years and moved to Python recently, nevertheless the core concepts remain the same be it the classes, functions or exception handling :) 🚀 FastAPI Insight: Why Your 4xx Errors Still Show “detail” (and how to fix it cleanly) While working with FastAPI, I came across a subtle but important behavior in error handling. 🔍 The Situation You raise an exception like this: raise HTTPException( status_code=422, detail={ "error_code": "VALIDATION_ERROR", "message": "Something went wrong" } ) But the response always comes back as: { "detail": { "error_code": "...", "message": "..." } } 🤔 Even though you passed a custom structure, FastAPI wraps everything inside "detail". 🧠 Key Insight HTTPException → controls the status code FastAPI → always wraps response inside detail You cannot change this behavior directly ⚠️ Common Mistake Catching all exceptions like this: except Exception as e: This also catches HTTPException ❌ Result → Your intended 4xx/5xx error may get converted into a 200 response (bad API design) ✅ Correct Pattern except HTTPException: raise # preserve original status code 💡 The Real Solution If you want a clean, consistent API response like: { "status": "error", "error": { ... } } 👉 You need to override FastAPI’s default behavior: @app.exception_handler(HTTPException) async def custom_handler(request, exc): return JSONResponse( status_code=exc.status_code, content={ "status": "error", "error": exc.detail } ) 🎯 Final Takeaway ✔️ Use HTTPException for proper HTTP semantics ✔️ Always re-raise it inside except blocks ✔️ Use a custom exception handler for consistent API contracts This small tweak can make your API: Cleaner More predictable Easier to integrate with frontend systems #FastAPI #BackendDevelopment #Python #APIDesign #SoftwareEngineering #CleanCode #Microservices
FastAPI 4xx Error Handling with HTTPException
More Relevant Posts
-
Stop writing Python like Java/C++ when thinking about backend performance. The 'Pythonic' way to approach background tasks isn't about threads for every little thing. It's about offloading work that doesn't need to happen immediately, so your main request handler can respond quickly. This frees up your web server to serve more incoming requests, rather than getting stuck waiting for a long-running process. Think of it like a restaurant: the waiter (your main request handler) takes your order and brings it to the kitchen. The kitchen staff (background workers) then prepare your food without the waiter standing there waiting. The waiter can then go take the next order. Here's a quick look: Okay (Blocking) # In your web request handler def process_data(request): longrunningtask() # This blocks the request until it's done return HttpResponse("Done!") Best (Non-Blocking with Background Worker) # In your web request handler def processdataasync(request): enqueuetask(longrunning_task) # Task is put in a queue, request returns immediately return HttpResponse("Task accepted, processing in background!") # Separate process/thread manages enqueuetask and longrunning_task Background workers improve backend performance by separating time-consuming operations from the main request-response cycle, allowing your application to handle more concurrent users. #Python #CodingTips
To view or add a comment, sign in
-
-
Stop writing Python like Java/C++. Most backend developers, coming from languages like Java or C++, tend to think about performance in terms of threading and blocking I/O. While that's a valid concern, Python offers a more idiomatic and often simpler approach to managing background tasks that can significantly boost backend performance. The 'Pythonic' way to think about background workers isn't about squeezing more out of a single process with complex threading. Instead, it's about offloading work that doesn't need to happen right now from the main request-response cycle. This allows your web server to respond to users faster, while the heavy lifting happens asynchronously in the background. Think of it like a restaurant: the waiter (your web server) takes your order quickly, and the chefs (background workers) prepare your meal without you waiting at the counter. Here's a quick example of the core idea: Okay (Blocking): from flask import Flask import time app = Flask(name) def longrunningtask(): time.sleep(5) # Simulates a slow operation print("Task finished!") @app.route('/') def index(): longrunningtask() # This blocks the entire request return "Request processed!" Best (Async with a Worker Queue - conceptual): from flask import Flask import time from yourworkerlibrary import enqueue_task # e.g., Celery, RQ app = Flask(name) def longrunningtask(): time.sleep(5) print("Task finished!") @app.route('/') def index(): enqueuetask(longrunning_task) # This returns immediately return "Request received! Task is processing in the background." The key insight here is that your main application should focus on quickly serving user requests. Anything that takes time and doesn't need to be in the immediate response – like sending emails, processing images, or generating reports – should be handled by a separate background worker process. This decoupling keeps your web server responsive and your users happy. Background workers improve backend performance by removing slow, non-essential tasks from the critical request-response path, allowing the main application to serve users much faster. #Python #CodingTips
To view or add a comment, sign in
-
-
Most developers switching to Go from Java or Python hit the same wall: there is no try-catch. Instead, Go returns errors as ordinary values and asks you to check them with `if err != nil` on almost every line. It looks like boilerplate. It is actually a design decision. Here are the 4 patterns every Go developer needs to know. 🧱 Pattern 1: Basic error return + defer A function signals failure by returning an error as its last value. `defer` guarantees cleanup runs when the function returns, on any path. No finally block needed. 🎁 Pattern 2: Wrapping errors with context Returning a raw error loses all information about where it happened. Use `fmt.Errorf` with `%w` to add context while preserving the original: return nil, fmt.Errorf("readUserFile: opening %q: %w", path, err) This turns error messages into a readable breadcrumb trail through your codebase. Use %w to wrap (callers can inspect). Use %v only when converting to a final log string. 🚩 Pattern 3: Sentinel errors + errors.Is When callers need to distinguish a specific condition, define a named sentinel at the package level and check it with errors.Is, not ==. Direct equality fails for wrapped errors. errors.Is unwraps the chain layer by layer until it finds a match. 🏗️ Pattern 4: Custom error types + errors.As When the caller needs structured data from the error (not just recognition), define a struct that implements the error interface. Extract it with errors.As, which searches the entire error chain by type to give you typed fields directly. ⚖️ The honest trade-offs ✅ Every error is visible at the call site ✅ No hidden control flow, no surprise jumps ✅ Code review is easier: no distant catch blocks to hunt through ❌ if err != nil repeated throughout every function ❌ No automatic stack trace (wrap consistently with function names as a fix) ❌ Errors can still be ignored with _ (use errcheck or staticcheck in CI) Go's philosophy: errors are normal outcomes, not exceptional events. Explicit is better than implicit. The verbosity is the feature. We built a full hands-on article where we construct a working CLI called userstore that demonstrates all 4 patterns together in one runnable program. 🔗 https://lnkd.in/gqVCS9ib
To view or add a comment, sign in
-
Embabel treats LLMs as participants in strongly typed workflows — not black boxes — and the Spring creator Rod Johnson spring says that gives Java developers an edge Python can't match. By Darryl Taft
To view or add a comment, sign in
-
Leetcode Practice - 8. String to Integer (atoi) The problem is solved using JAVA. Implement the myAtoi(string s) function, which converts a string to a 32-bit signed integer. The algorithm for myAtoi(string s) is as follows: ✔ Whitespace: Ignore any leading whitespace (" "). ✔ Signedness: Determine the sign by checking if the next character is '-' or '+', assuming positivity if neither present. ✔ Conversion: Read the integer by skipping leading zeros until a non-digit character is encountered or the end of the string is reached. If no digits were read, then the result is 0. ✔ Rounding: If the integer is out of the 32-bit signed integer range [-231, 231 - 1], then round the integer to remain in the range. Specifically, integers less than -231 should be rounded to -231, and integers greater than 231 - 1 should be rounded to 231 - 1. Return the integer as the final result. Example 1: Input: s = "42" Output: 42 Explanation: The underlined characters are what is read in and the caret is the current reader position. Step 1: "42" (no characters read because there is no leading whitespace) ^ Step 2: "42" (no characters read because there is neither a '-' nor '+') ^ Step 3: "42" ("42" is read in) #LeetCode #Java #StringHandling #CodingPractice #ProblemSolving #DSA #DeveloperJourney #TechLearning
To view or add a comment, sign in
-
-
🔥 You write Arrays.sort() in Java all the time… but do you know what actually happens behind the scenes? Most developers don’t - and the truth is way more interesting than you’d expect 👇 ⚙️ 1. Sorting Primitive Types (int, double, char…) Java fires up Dual‑Pivot QuickSort ⚡ Faster than classic QuickSort ⚡ Highly optimized for real‑world data ⚠️ Not stable - but that’s irrelevant for primitives Hidden optimizations you might’ve never noticed: • Tiny arrays → switches to Insertion Sort • byte, short, char → may use Counting Sort for blazing speed 🧩 2. Sorting Objects (String, Integer, custom classes) Java switches to the legendary TIMSORT (yes, the same one Python uses) Why it’s brilliant: ✔ Hybrid of Merge Sort + Insertion Sort ✔ Detects natural order in your data ✔ Stable — crucial for objects ✔ Worst case: O(n log n) This is why object sorting feels surprisingly fast even on messy datasets. 🚀 3. Sorting Big Arrays? Java Goes Parallel Arrays.parallelSort() taps into the Fork/Join framework ✔ Splits the array ✔ Sorts chunks in parallel ✔ Merges everything efficiently A huge win for 10k+ elements on multi‑core systems. 🧠 The Cool Part Java doesn’t rely on one “universal” algorithm. It adapts intelligently based on: • Data type • Array size • Hardware • Real‑world patterns That’s why a single line of code can deliver such impressive performance. 🎯 Why This Matters Understanding this helps you: • Write more efficient, predictable code • Choose between sort() and parallelSort() • Stand out in interviews • Appreciate the engineering behind everyday APIs 💬 Did you already know Java uses multiple algorithms internally - or is this a new discovery for you? #Java #Algorithms #SoftwareEngineering #Backend #CodingInterview #ProgrammingInsights
To view or add a comment, sign in
-
Java and JavaScript are not call by reference. It's time to clarify a common myth: “Java / JavaScript pass objects by reference” is not true. Both languages strictly use call by value, similar to Python. Why the confusion? When you pass objects, changes can sometimes reflect outside the function, which may appear to be call by reference. However, it’s actually value copying. To understand this, consider the memory architecture: - Stack: Stores variables and function calls, with each call creating a new stack frame. - Heap: Stores actual objects. Here’s what happens during a function call: 1. Variable Creation: - Primitives store actual values. - Objects store references (memory addresses). 2. Function / Method Call: - A new stack frame is created, and parameters become new local variables. 3. Core Step — Value Copy: - The value of the argument is copied. For primitives, the data is copied; for objects, the reference (address) is copied. It’s still a copy in both cases. 4. Inside Function: - Mutation works (e.g., 'obj.name = "Ishwar"' changes the same object in the heap). - Reassignment does not work (e.g., 'obj = new Object()' only changes the local copy). 5. Function Ends: - The stack frame is destroyed, and original variables remain unchanged. Mental Model: The caller variable copies the value to the function parameter, providing no direct access to the original variable—only a copy is used. This behavior applies to multiple languages: - Java: Call by value - JavaScript: Call by value - Python: Call by value (object reference) - C#: Call by value (default) Final truth: “Everything is pass by value. Some values just happen to be references.” 🔖 Follow CodeWithIshwar for more deep dives into real-world programming concepts. #CodeWithIshwar #Java #JavaScript #Python #Programming #SoftwareEngineering #BackendDevelopment #Coding #Developers #Tech #ComputerScience #OOP #Debugging
To view or add a comment, sign in
-
𝐂𝐚𝐧 𝐰𝐞 𝐨𝐯𝐞𝐫𝐫𝐢𝐝𝐞 𝐭𝐡𝐞 "𝐦𝐚𝐢𝐧()" 𝐦𝐞𝐭𝐡𝐨𝐝 𝐢𝐧 𝐉𝐚𝐯𝐚? In my previous post, we discussed that the "main()" method is static. No — we cannot override the "main()" method Why ? Because "main()" is static. And we cannot override static methods And in Java: 📃Overriding happens at runtime ⏱️ 📃 It depends on objects 👤 But ❌ Static methods belong to the class ❌ They are loaded during class loading time (before objects are created) 🔍𝐖𝐡𝐚𝐭 𝐚𝐜𝐭𝐮𝐚𝐥𝐥𝐲 𝐡𝐚𝐩𝐩𝐞𝐧𝐬 𝐭𝐡𝐞𝐧? You can write a main() method in a child class ❌ But it does not override the parent’s main(). It’s called "𝐌𝐞𝐭𝐡𝐨𝐝 𝐇𝐢𝐝𝐢𝐧𝐠". 𝐜𝐥𝐚𝐬𝐬 𝐏𝐚𝐫𝐞𝐧𝐭 { 𝐩𝐮𝐛𝐥𝐢𝐜 𝐬𝐭𝐚𝐭𝐢𝐜 𝐯𝐨𝐢𝐝 𝐦𝐚𝐢𝐧(𝐒𝐭𝐫𝐢𝐧𝐠[] 𝐚𝐫𝐠𝐬) { 𝐒𝐲𝐬𝐭𝐞𝐦.𝐨𝐮𝐭.𝐩𝐫𝐢𝐧𝐭𝐥𝐧("𝐏𝐚𝐫𝐞𝐧𝐭 𝐦𝐚𝐢𝐧"); } } 𝐜𝐥𝐚𝐬𝐬 𝐂𝐡𝐢𝐥𝐝 𝐞𝐱𝐭𝐞𝐧𝐝𝐬 𝐏𝐚𝐫𝐞𝐧𝐭 { 𝐩𝐮𝐛𝐥𝐢𝐜 𝐬𝐭𝐚𝐭𝐢𝐜 𝐯𝐨𝐢𝐝 𝐦𝐚𝐢𝐧(𝐒𝐭𝐫𝐢𝐧𝐠[] 𝐚𝐫𝐠𝐬) { 𝐒𝐲𝐬𝐭𝐞𝐦.𝐨𝐮𝐭.𝐩𝐫𝐢𝐧𝐭𝐥𝐧("𝐂𝐡𝐢𝐥𝐝 𝐦𝐚𝐢𝐧"); } } 𝐩𝐮𝐛𝐥𝐢𝐜 𝐜𝐥𝐚𝐬𝐬 𝐃𝐞𝐦𝐨 { 𝐩𝐮𝐛𝐥𝐢𝐜 𝐬𝐭𝐚𝐭𝐢𝐜 𝐯𝐨𝐢𝐝 𝐦𝐚𝐢𝐧(𝐒𝐭𝐫𝐢𝐧𝐠[] 𝐚𝐫𝐠𝐬) { 𝐏𝐚𝐫𝐞𝐧𝐭 𝐩 = 𝐧𝐞𝐰 𝐂𝐡𝐢𝐥𝐝(); 𝐩.𝐦𝐚𝐢𝐧(𝐚𝐫𝐠𝐬); // 𝐜𝐚𝐥𝐥𝐬 𝐏𝐚𝐫𝐞𝐧𝐭 𝐦𝐚𝐢𝐧 𝐂𝐡𝐢𝐥𝐝.𝐦𝐚𝐢𝐧(𝐚𝐫𝐠𝐬); // 𝐜𝐚𝐥𝐥𝐬 𝐂𝐡𝐢𝐥𝐝 𝐦𝐚𝐢𝐧 } } Output : Parent main Child main ♟️These main() methods are not called automatically by the JVM — they run only when we explicitly invoke them. ♟️Only main(String[] args) is invoked automatically by JVM. Other overloaded or hidden main() methods are executed only when explicitly called. 🚀 𝐅𝐢𝐧𝐚𝐥 𝐓𝐚𝐤𝐞𝐚𝐰𝐚𝐲 "main()" method cannot be overridden because it is static — it can only be hidden #Java #JavaDeveloper #JavaBackend #Programming #TechJourney #LearnBySharing #JavaConcepts #OOP #InterviewPrep
To view or add a comment, sign in
-
GitVoyant v0.3.0. Temporal code intelligence now runs across Python, JavaScript, Java, and Go. Four language-specific analyzers behind a single protocol. Tree-sitter for unified AST parsing. Automatic language detection. Static analysis tells you a file is complex. GitVoyant tells you whether that complexity is growing, shrinking, or stable, and at what rate. https://lnkd.in/g4fNbdRg
To view or add a comment, sign in
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development