Apply to my task
arXiv:2602.02896 ★ 90 Feb 2, 2026

Failure-Aware Framework: A Map of LLM Code-Generation Failure Types and the Fixes That Work

Key result

Self-Critique delivers exactly 0% improvement on half of the unfinished projects. That's not a bug; it's the method's boundary. The framework lets you pick a code-improvement strategy that works instead of trial and error. The decision framework is a 'failure type → method' map: logic gaps (a forgotten function) → Self-Critique (the model spots them in review); external integration (RabbitMQ not configured) → RAG-Assisted (drop a tutorial into the context). The evidence: Self-Critique 0% vs. RAG 100% on integration, across 18 experiments on real GitHub projects.

01

TL;DR

The Failure-Aware Framework is a system for choosing a code-improvement method when basic progressive prompting (step-by-step generation: requirements → design → tests → code) falls short. The core idea: different failure types need different fix strategies: Self-Critique (self-review), Multi-Model Collaboration (different models for design and code) or RAG-Assisted (documentation in the context).

Progressive prompting delivers 96.9% task completion vs. 80.5% for a direct prompt, but 32% of projects still end up unfinished. The failures fall into 4 types: logic (missing validation), integration (API not wired up), domain (unknown medical rules), infrastructure (Docker config not set up). Self-Critique works great on logic failures (they're visible in code review), but gives 0% improvement on integration failures: the model doesn't know how to configure RabbitMQ no matter how many times it reviews the code. RAG-Assisted solves this by dropping RabbitMQ tutorials right into the context.

The decision framework is a "failure type → method" map: for logic failures use Self-Critique (fast, 138 minutes); for integration/domain/infrastructure use RAG-Assisted (193 minutes, 31.5 min per percentage point of improvement); for critical tasks use Multi-Model (279 minutes, but 100% on 5 of 6 projects). It's empirically proven: not every method works everywhere, and the choice depends on what kind of gap you're dealing with.

Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.

02

Method Blueprint

Baseline: Progressive Prompting

STEP 1: Requirements analysis → task list
STEP 2: Architecture design → project structure
STEP 3: Test specification → test scenarios
STEP 4: Code generation → implementation

Each step is a separate prompt in the same session.

Enhancement 1: Self-Critique (self-review)

STEPS 1-4: Progressive Prompting
STEP 5: "Review the code. Are all requirements met? What's missing?"
STEP 6: The LLM finds the gaps → generates fixes
STEP 7: Repeat 5-6 until the LLM says "everything's done"

An iterative loop in the same session.

Enhancement 2: Multi-Model Collaboration

In ChatGPT (GPT-5):
  STEP 1: Requirements analysis
  STEP 2: Architecture design → detailed specification

In Claude (Sonnet 4.5):
  STEP 3: Paste in the specification from GPT
  STEP 4: Generate code from the design

Switching between chats: you carry the specification over by hand.

Enhancement 3: RAG-Assisted (documentation in the context)

PREP: Find documentation/examples (official docs, GitHub projects)
STEPS 1-4: Progressive Prompting + add to the prompt:
  "Using these examples and documentation [paste], implement the requirements"

Copy-paste the documentation into every relevant prompt.

03

Example

Task: You're building a WhatsApp ordering bot for a coffee shop. Progressive prompting generated the basic code (menu, cart, commands), but couldn't integrate Stripe payments: the code just has a stub # TODO: payment integration.

Diagnosing the failure type

You look at the code: the cart logic is there, validation is there, but the external API (Stripe) isn't wired up. That's an External Integration Failure.

According to the decision framework: - 1st choice for integration failures: RAG-Assisted - 2nd choice: Multi-Model - 3rd choice: Self-Critique (doesn't work on these failures)

Applying RAG-Assisted

Prompt:

Using the official Stripe documentation for Python and the examples below, 
finish the create_payment() function for paying for an order in the WhatsApp bot.

[paste the Quick Start page from stripe.com/docs/api]
[paste a checkout.Session.create() example from Stripe's GitHub samples]

Requirements:
- Create a payment for the cart total
- Return a payment link to the user
- Handle the payment confirmation webhook

Current function code:
[paste the stub from the generated code]

Result: The model fills the stub with working code: the stripe import, setting stripe.api_key from STRIPE_SECRET_KEY, a call to stripe.checkout.Session.create() with the right parameters (line_items, currency="usd", mode="payment"), and handling of session.url. If progressive prompting didn't know how to work with a specific API, RAG gives it an exact template.

04

Why it works

The LLM's weakness: The model is trained on general patterns but doesn't know the specifics of particular APIs, frameworks and domain rules. When it sees "integrate Stripe," it generates plausible but broken code, because it never saw the current 2024 documentation in its training data.

The LLM's strength: It's excellent at adapting templates to a new context. Give it a checkout.Session.create() example with parameters and it immediately gets the logic and plugs in the right values from your task. This isn't blind copying: the model understands the structure and transfers the pattern.

How the methods work: - Self-Critique uses the LLM's ability to analyze code as text. It works when the error is visible: a missing function, forgotten validation. It doesn't work when outside knowledge is needed (how to configure RabbitMQ). - Multi-Model uses model specialization: GPT-5 is stronger at system design, Claude at code generation. Splitting the work reduces ambiguity in the requirements. - RAG-Assisted feeds in concrete examples and official patterns, turning "figure out how the API works" into "adapt this working example."

Control levers: - Number of Self-Critique cycles: you can stop after 2-3 iterations instead of "until it says done," which saves time once it's clear the method isn't helping - Models in Multi-Model: you can swap GPT-5 for GPT-4o (cheaper) for the design step if the project is simple - Depth of RAG materials: for simple tasks a Quick Start is enough; complex ones need GitHub examples and best practices - Type of documentation in RAG: official docs (accuracy) vs. Stack Overflow (practicality) vs. GitHub (real code)

05

Prompt template

1. Progressive Prompting (baseline)

Step 1: Analyze the requirements and make a task list for the project: {project_description}

---

Step 2: Based on the task list, design the architecture: code structure, components, API, data models.

---

Step 3: Write a test specification for each component: which scenarios to test, edge cases.

---

Step 4: Implement the project code following the architecture and tests from the previous steps.

Placeholders: {project_description}: what you'd normally type into the chat: "A WhatsApp bot for a coffee shop with a menu, cart and payments."


2. Self-Critique (self-review)

[After progressive prompting has generated the code]

Review the generated code carefully:
- Are all the tasks from step 1 implemented?
- Which requirements are missing or only partly done?
- Where are the stubs or TODOs in the code?

List the gaps, then fix them.

[Repeat until the LLM answers "everything is done" or you see it's no longer improving]

3. Multi-Model Collaboration

In ChatGPT (GPT-5):

Step 1: Analyze the requirements for the project: {project_description}

---

Step 2: Design a detailed architecture:
- Component structure
- API endpoints / interfaces
- Data models
- Integration patterns for external services

Produce a complete specification to hand off to another developer.

In Claude (Sonnet 4.5):

Implement the code according to the following architecture specification:

[paste the specification from GPT]

Follow the design exactly; use the specified patterns and structure.

4. RAG-Assisted (documentation in the context)

Using the documentation and examples below as reference, implement {task}:

[paste the official API/framework documentation]
[paste code examples from GitHub / tutorials]

Requirements:
{list_of_specific_requirements}

Current code (if any):
{code_with_stubs}

Placeholders: - {task}: "Stripe payment integration for a WhatsApp bot" - Documentation: copy from the Quick Start and API Reference pages - Examples: search GitHub for "{library} example" and take the relevant chunks - {list_of_specific_requirements}: specifics: "create a payment for the cart total, return a link, handle the webhook" - {code_with_stubs}: whatever progressive prompting already generated with TODOs

Where to find RAG materials: - Official docs: stripe.com/docs, developers.facebook.com/docs/whatsapp - GitHub: search "{library name} example" → check the Issues and Wiki - Tutorials: dev.to, Medium; filter by recency (2023-2024)

06

Decision Framework: what to use when

1. Diagnose the failure type in the generated code:

   Logic (Local Logic):
   - Missing function
   - Forgotten validation
   - Incomplete business logic
   → 1st choice: Self-Critique
   → 2nd choice: RAG-Assisted

   Integration (External Integration):
   - API not wired up
   - Service not configured
   - External SDK used incorrectly
   → 1st choice: RAG-Assisted
   → 2nd choice: Multi-Model

   Domain (Domain Knowledge):
   - Industry-specific rules
   - Business processes
   - Regulatory requirements
   → 1st choice: RAG-Assisted
   → 2nd choice: Multi-Model

   Infrastructure:
   - Docker configs
   - CI/CD pipeline
   - Deployment
   → 1st choice: RAG-Assisted
   → 2nd choice: Multi-Model

2. Apply the 1st choice. If it doesn't help → 2nd choice.

3. For critical tasks (production code) go straight to Multi-Model: 
   slower but more reliable (100% in 83% of cases).

How to diagnose: - Open the generated code - Find the TODOs, stubs, missing pieces - Ask yourself: "Is this visible in the code, or does it need outside knowledge?" - Visible (missing function, no check) → Logic → Self-Critique - Needs knowledge (how the API works) → Integration/Domain → RAG-Assisted

07

Limitations

⚠️ Requires a diagnosis: You need to identify the failure type correctly. Apply Self-Critique to an integration problem and you'll burn 138 minutes for nothing (0% improvement in the study).

⚠️ Multi-Model = two subscriptions: You need access to GPT-5 (or GPT-4) and Claude Sonnet 4.5. If you only have one chat, use RAG-Assisted as the all-purpose method.

⚠️ RAG means finding materials: Effectiveness depends on the quality of the documentation. If the API is obscure and examples are scarce, the method delivers less. In the study, RAG couldn't handle project P10 (complex inventory logic): no ready-made examples, only generic CRUD patterns.

⚠️ Code-specific: The framework was built for code generation, but the principles are universal: Self-Critique for errors fixable through review, RAG for tasks that need outside knowledge, Multi-Model for critical cases.

⚠️ Time vs. accuracy: Self-Critique is the fastest (138 min on average) but doesn't work everywhere. Multi-Model is the slowest (279 min) but the most reliable. RAG-Assisted is the sweet spot (193 min, best efficiency at 31.5 min/percentage point).

08

Why the method works: the study's logic

The researchers took 25 real projects from GitHub (e-commerce, booking, microservices, infrastructure) and compared direct prompting (one "write the code" prompt) with progressive prompting. Result: progressive delivered 96.9% completion vs. 80.5% for direct (a large effect, Cohen's d=1.63, p<0.001), but 8 of 25 projects (32%) were left unfinished, with 19 tasks not implemented.

The team classified these 19 gaps into 4 types by the nature of the missing functionality (not syntax, but what exactly was left out): logic errors (missing inventory validation), integration (RabbitMQ not configured), domain (medical rules unknown), infrastructure (missing Docker configs). They then picked 6 representative projects (covering all 4 types) and ran 3 enhancement methods on each = 18 experiments.

The surprise: Self-Critique gave exactly 0% improvement on 3 of 6 projects (P8, P18, P25): the ones with external integrations and domain knowledge. No amount of iterative code review lets the model conjure up how to configure RabbitMQ out of thin air. But on projects P2 and P10 (logic gaps: a forgotten API endpoint, skipped validation), Self-Critique delivered 100% in 115-155 minutes. That revealed the method's clear boundary: it only works on code-reviewable failures, the ones you can see when reviewing the code.

Multi-Model hit 100% on 5 of 6 projects (83%) but was never the fastest: 279 minutes on average vs. 193 for RAG and 138 for Self-Critique. RAG-Assisted showed the best versatility: 100% on every integration/domain/infrastructure project, plus top efficiency at 31.5 minutes per percentage point of improvement vs. 47.4 for Multi-Model. The paradox: RAG and Multi-Model both averaged 99.2%, but RAG won 4 of 6 projects on speed.

The practical insight: There's no universal "best method." Self-Critique is a fast niche tool (it works on only 1 of 4 failure types). RAG-Assisted is the all-purpose workhorse (works everywhere with top efficiency). Multi-Model is insurance for critical tasks (the most reliable, but expensive in time). The decision framework is an empirical map: each failure type gets a method with proven effectiveness, no trial and error.

09

Resources

Failure-Aware Enhancements for Large Language Model (LLM) Code Generation: An Empirical Study on Decision Framework
Jianru Shen, Zedong Peng, Lucy Owen, University of Montana
Experiment data: https://doi.org/10.5281/zenodo.17637008

Research digest

Key result

Self-Critique delivers exactly 0% improvement on half of the unfinished projects. That's not a bug; it's the method's boundary. The framework lets you pick a code-improvement strategy that works instead of trial and error. The decision framework is a 'failure type → method' map: logic gaps (a forgotten function) → Self-Critique (the model spots them in review); external integration (RabbitMQ not configured) → RAG-Assisted (drop a tutorial into the context). The evidence: Self-Critique 0% vs. RAG 100% on integration, across 18 experiments on real GitHub projects.

Principle

Diagnose the type of gap → apply the method proven to work. Missing logic (visible in code review) → Self-Critique fixes it fast, in 138 minutes. API used incorrectly (needs outside knowledge of how the SDK works) → RAG-Assisted feeds in official examples. Critical production code → Multi-Model: GPT for system design, Claude for code generation. Slower (279 min), but 100% in 83% of cases. The key point: Self-Critique's boundary is that it only works on code-reviewable failures, the ones visible when analyzing the code. No amount of iterative checking lets the model conjure up how to configure a specific API out of thin air.

Why it works

The LLM's weakness: the model doesn't know the specifics of particular APIs and frameworks in their current versions. It sees 'integrate Stripe' and generates plausible but broken code, because it never saw the 2024 documentation in its training data. The LLM's strength: it's excellent at adapting templates to a new context. Give it a checkout.Session.create() example with parameters and it immediately gets the logic and plugs in the right values from the task. Progressive prompting (requirements→design→tests→code) delivers 96.9% completion vs. 80.5% for a direct prompt (Cohen's d=1.63, p<0.001), but 32% of projects stay unfinished. Self-Critique gives 0% on 3 of 6 projects (external integration); RAG-Assisted gives 100% on the same projects. RAG has top efficiency: 31.5 minutes per percentage point of improvement vs. 47.4 for Multi-Model.

When to apply

Code generation in ChatGPT/Claude → specifically when progressive prompting left gaps (TODO stubs, missing logic, API not wired up), especially for projects with external integrations (payment systems like Stripe/PayPal, RabbitMQ message queues, niche SDKs) and domain knowledge (medical rules, financial regulation). NOT a fit for simple scripts where direct prompting succeeds right away: the framework is for real projects with 10+ tasks.

Mini recipe

1. Generate the base code: progressive prompting, 4 separate prompts in one session: `Analyze the requirements and make a task list` → `Design the architecture` → `Write a test specification` → `Implement the code` 2. Diagnose the gaps: open the generated code, find the TODOs/stubs, ask 'is this visible in the code or does it need outside knowledge?' Visible (missing function) = logic failure; needs knowledge (how the API works) = integration 3. Pick the method by type: missing logic → Self-Critique `Review the code carefully. Which requirements are missing? Fix them`; API not wired up → RAG-Assisted (paste the official documentation + GitHub examples into the prompt); critical project → Multi-Model (GPT for design, carry the spec over to Claude for code) 4. Apply until it's fixed: repeat Self-Critique iteratively until it says 'everything's done'; for RAG feed in the Quick Start + tutorials; for Multi-Model one GPT→Claude cycle is usually enough

Examples

[BAD]: `Write a WhatsApp bot for a coffee shop with a menu, cart and Stripe payments`: direct prompting leaves a `# TODO: payment integration` stub, because the model doesn't know the current 2024 Stripe API documentation [GOOD]: Progressive prompting generated the base, but the API isn't wired up. Diagnosis: External Integration Failure. I apply RAG-Assisted and put into the prompt: `Using the official Stripe documentation for Python and the examples below, finish the create_payment() function` + the Quick Start pasted from stripe.com/docs + a checkout.Session.create() example from GitHub. The model fills the stub with working code with the right parameters: line_items, currency='usd', mode. Self-Critique would give 0% here: no matter how often it reviews the code, the model can't conjure up the API spec.

In plain words

AI models write code not like programmers but like extremely well-read storytellers. When you ask an LLM to build an app, it doesn't “think” about the logic; it predicts the most likely chunks of text. Progressive prompting, where we go from requirements to design and only then to code, often trips over reality. The model just can't handle the specifics: it knows what code looks like “on average,” but has no clue about the quirks of a particular library or a fresh API. Instead of a working service you get a pretty shell with comments like #finish this yourself.

It's like hiring a contractor off Craigslist who swears he can do everything but has only ever seen a smart-home install in the movies. He'll cheerfully hang the wallpaper, but the moment he gets to configuring the controllers, he'll start improvising and end up frying the wiring. The Failure-Aware Framework is the supervisor who slaps his hand in time and says: “Okay, you're clearly botching this, call for backup or read the manual.” Instead of banging its head against the same wall forever, the system analyzes the type of failure and changes tactics on the fly.

The big idea here is division of labor. When the code falls apart, the framework switches on one of three modes. Self-Critique makes the model hunt for its own screwups by looking at the result. Multi-Model Collaboration is when one model draws up the architecture and a second, more powerful one writes the code, so they don't infect each other with errors. But the most important one is RAG-Assisted, where the model literally gets up-to-date documentation shoved into its hands. If it doesn't know how payments through a specific provider work in 2024, it doesn't hallucinate; it goes and reads the fresh manual.

This approach is a lifesaver for any complex project, whether it's a coffee shop bot or a warehouse inventory system. It was tested on code, but the principle is universal: you can't demand the impossible from AI if it doesn't have the data. Instead of hoping the model “knows everything,” you need a system that understands where knowledge ends and total nonsense begins. It's a shift from blind faith in generation to deliberate quality control, where each type of error gets its own fix.

Bottom line: stop torturing a single model with endless clarifications; it doesn't work. If the baseline can't cope, bring in Failure-Aware logic: split the roles, plug in outside knowledge and make the AI critique itself. Either you set up this pipeline, or you keep scrubbing hallucinations and stubs out of the code by hand. In a world where APIs change every month, only software that knows when to admit it doesn't know something will survive.

AI lab assistant

Apply this study to your task

Describe what you're working on. AI takes the method and the measured results from this paper and adapts them to your case, or writes a ready prompt built on them.

Based on Failure-Aware Framework: A Map of LLM Code-Generation Failure Types and the Fixes That Work arXiv:2602.02896

Sign in to apply this study New accounts get 50 free credits.