DEV Community

oshi-git
oshi-git

Posted on

Solving the 'resource_func' Mystery: How I Made Ballerina's Compiler More User-Friendly

title: Solving the 'resource_func' Mystery: How I Made Ballerina's Compiler More User-Friendly
published: true
description: A deep dive into improving compiler error messages in the Ballerina programming language - from identifying the issue to implementing a production-ready fix
tags: ballerina, opensource, compiler, developerexperience

Solving the 'resource_func' Mystery: How I Made Ballerina's Compiler More User-Friendly

When developers encounter compiler errors, clear and actionable error messages can mean the difference between quick resolution and hours of frustration. This is the story of how I improved the Ballerina compiler's error messaging system to provide better developer experience.

The Problem: A Cryptic Error Message

While exploring the Ballerina programming language, I encountered issue #43815 in the Ballerina GitHub repository. Developers were reporting a confusing compiler error that displayed:

error: this resource_func must return a result
Enter fullscreen mode Exit fullscreen mode

The issue? resource_func isn't valid Ballerina syntax. The correct syntax uses two separate words: resource function. This seemingly minor discrepancy was causing significant confusion among developers, particularly those new to Ballerina's resource function paradigm.

Why This Matters

In enterprise software development, developer experience (DX) is paramount. Clear error messages:

  • Reduce debugging time
  • Lower the learning curve for new developers
  • Improve code quality by guiding developers toward correct implementations
  • Decrease support burden on development teams

For a cloud-native programming language like Ballerina, which emphasizes developer productivity, this error message was undermining one of its core value propositions.

Investigation: Diving Into the Compiler Architecture

Understanding the Codebase

The Ballerina compiler is a sophisticated multi-module system written in Java. My investigation began with systematic code navigation:

  1. Identifying the error origin: Located the diagnostic error code BCE2095 associated with this message
  2. Tracing the error flow: Found the error was triggered in ReachabilityAnalyzer.java during semantic analysis
  3. Understanding the root cause: Discovered the issue at line 583-584

The Root Cause

The problematic code was deceptively simple:

this.dlog.error(closeBracePos, DiagnosticErrorCode.INVOKABLE_MUST_RETURN,
    funcNode.getKind().toString().toLowerCase());
Enter fullscreen mode Exit fullscreen mode

The compiler was calling getKind().toString().toLowerCase() on function nodes. For resource functions, this returned the enum value RESOURCE_FUNC (with underscore), which was then directly inserted into the error message template:

invokable.must.return=this {0} must return a result
Enter fullscreen mode Exit fullscreen mode

Result: "this resource_func must return a result" instead of "this resource function must return a result"

The Solution: Implementing Proper Function Kind Formatting

Design Considerations

As an enterprise-grade compiler, any modification needed to:

  • Maintain backward compatibility
  • Follow established code patterns
  • Be maintainable and extensible
  • Not impact performance
  • Handle all function types correctly

Implementation Strategy

I implemented a helper method to properly format function kind names for user-facing error messages:

private String getFunctionKindName(BLangFunction funcNode) {
    String kind = funcNode.getKind().toString().toLowerCase();
    // Convert internal enum representation to user-friendly format
    if (kind.equals("resource_func")) {
        return "resource function";
    }
    return kind;
}
Enter fullscreen mode Exit fullscreen mode

Then modified the error logging call:

// Before
this.dlog.error(closeBracePos, DiagnosticErrorCode.INVOKABLE_MUST_RETURN,
    funcNode.getKind().toString().toLowerCase());

// After  
this.dlog.error(closeBracePos, DiagnosticErrorCode.INVOKABLE_MUST_RETURN,
    getFunctionKindName(funcNode));
Enter fullscreen mode Exit fullscreen mode

Why This Approach Works

  1. Separation of concerns: Internal representation (RESOURCE_FUNC) remains unchanged while user-facing text is formatted appropriately
  2. Extensibility: Easy to add formatting for other function types if needed
  3. Minimal footprint: Single helper method, no changes to diagnostic infrastructure
  4. Zero performance impact: Simple string comparison executed only during error conditions
  5. Maintainability: Clear, self-documenting code that future contributors can easily understand

The Contribution Process

Technical Workflow

Contributing to a major open-source project requires following established protocols:

  1. Forked the repository: Created personal fork of ballerina-platform/ballerina-lang
  2. Created feature branch: fix-issue-43815 for isolation
  3. Made targeted changes: Modified only ReachabilityAnalyzer.java
  4. Committed with proper messaging: Clear commit message referencing the issue
  5. Submitted Pull Request: #44407
  6. Signed CLA: Completed Contributor License Agreement

Code Review Considerations

The PR includes:

  • Minimal diff: Only 13 lines changed, 5 removed
  • Clear intent: Single responsibility - fix error message formatting
  • No breaking changes: Backward compatible modification
  • No new dependencies: Uses existing infrastructure

Impact and Results

Immediate Benefits

Before:

error: this resource_func must return a result
Enter fullscreen mode Exit fullscreen mode

Developers confused by non-existent resource_func syntax

After:

error: this resource function must return a result  
Enter fullscreen mode Exit fullscreen mode

Clear indication of correct syntax with two words

Broader Implications

This fix demonstrates several software engineering principles:

  1. User-Centric Design: Error messages should use language users understand
  2. Attention to Detail: Small UX improvements compound over time
  3. Systematic Debugging: Methodical code navigation yields results
  4. Clean Implementation: Simple solutions are often the best

Technical Learnings

Compiler Architecture Insights

Working with the Ballerina compiler provided valuable insights:

  • Semantic Analysis Phase: Error detection happens after parsing, during semantic analysis
  • Diagnostic System: Centralized error message management through property files
  • AST Traversal: Visitor pattern used for analyzing Abstract Syntax Trees
  • Error Reporting: Separation between error detection and message formatting

Best Practices in Large Codebases

Contributing to enterprise software taught me:

  • Read before you write: Understanding existing patterns prevents technical debt
  • Follow established conventions: Consistency matters in team environments
  • Document your reasoning: Clear commit messages and PR descriptions facilitate review
  • Test thoroughly: Even small changes need verification
  • Engage with the community: Responsive communication speeds up acceptance

Why This Matters for Developer Experience

The Cost of Poor Error Messages

Research shows that developers spend approximately 50% of their time debugging. Unclear error messages:

  • Increase time-to-resolution
  • Create frustration and cognitive load
  • May cause developers to abandon a technology
  • Generate unnecessary support requests

The Value of Continuous Improvement

Every error message improvement:

  • Saves collective developer hours
  • Improves language adoption
  • Demonstrates project maturity
  • Builds community confidence

Conclusion

Improving developer experience isn't always about major features or performance optimizations. Sometimes, it's about the small details - like ensuring error messages use the correct terminology.

This contribution to Ballerina demonstrates that open source is accessible to developers at all levels. You don't need to implement complex algorithms or major features to make meaningful contributions. Sometimes, the most valuable improvements are the ones that reduce friction in daily development workflows.

Key Takeaways

  1. Start with good first issues: They're marked as such for a reason
  2. Understand before you code: Time spent reading code is time well invested
  3. Think about the user: Every message, error, or log is communication
  4. Small PRs get merged faster: Focused changes are easier to review
  5. Documentation matters: Well-documented contributions get better reception

Get Involved

Interested in contributing to Ballerina? Here's how to start:

Every major open-source project started with someone's first contribution. This was mine - what will yours be?


About the Author

I'm a software engineering student passionate about compiler design, developer tools, and open-source contributions. This article documents my first contribution to the Ballerina programming language. Connect with me on GitHub.

Pull Request: #44407 - Fix error message for resource functions


Found this helpful? Follow me for more articles on open-source contribution, compiler design, and developer tools.

Ballerina #OpenSource #CompilerDesign #DeveloperExperience #SoftwareEngineering

Top comments (0)