Skip to main content
Glama
elad12390

Web Research Assistant

by elad12390

translate_error

Find solutions for error messages and stack traces by searching Stack Overflow and GitHub for relevant fixes with code examples.

Instructions

Find solutions for error messages and stack traces from Stack Overflow and GitHub.

Takes an error message or stack trace and finds relevant solutions with code examples.
Automatically detects language and framework, extracts key error information, and
searches for the best solutions ranked by votes and relevance.

Perfect for:
- Debugging production errors
- Understanding cryptic error messages
- Finding working code fixes
- Learning from similar issues

Examples:
- translate_error("TypeError: Cannot read property 'map' of undefined", reasoning="Debugging React app crash")
- translate_error("CORS policy: No 'Access-Control-Allow-Origin' header", reasoning="Fixing API integration", framework="FastAPI")
- translate_error("error[E0382]: borrow of moved value", reasoning="Learning Rust ownership", language="rust")

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
error_messageYes
reasoningYes
languageNo
frameworkNo
max_resultsNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The main handler function for the 'translate_error' tool. It parses the input error message using ErrorParser, constructs an optimized search query, performs a web search prioritizing Stack Overflow, filters irrelevant results, and formats a structured response with solutions, parsed error info, and usage tips. Includes comprehensive error handling, tracking, and result formatting.
    async def translate_error(
        error_message: Annotated[str, "The error message or stack trace to investigate"],
        reasoning: Annotated[str, "Why you're investigating this error (required for analytics)"],
        language: Annotated[str | None, "Programming language (auto-detected if not provided)"] = None,
        framework: Annotated[
            str | None, "Framework context (e.g., 'React', 'FastAPI', 'Django')"
        ] = None,
        max_results: Annotated[int, "Number of solutions to return (1-10)"] = 5,
    ) -> str:
        """
        Find solutions for error messages and stack traces from Stack Overflow and GitHub.
    
        Takes an error message or stack trace and finds relevant solutions with code examples.
        Automatically detects language and framework, extracts key error information, and
        searches for the best solutions ranked by votes and relevance.
    
        Perfect for:
        - Debugging production errors
        - Understanding cryptic error messages
        - Finding working code fixes
        - Learning from similar issues
    
        Examples:
        - translate_error("TypeError: Cannot read property 'map' of undefined", reasoning="Debugging React app crash")
        - translate_error("CORS policy: No 'Access-Control-Allow-Origin' header", reasoning="Fixing API integration", framework="FastAPI")
        - translate_error("error[E0382]: borrow of moved value", reasoning="Learning Rust ownership", language="rust")
        """
        start_time = time.time()
        success = False
        error_msg = None
        result = ""
        parsed = None
    
        try:
            max_results = max(1, min(max_results, 10))
    
            # Parse the error message
            parsed = error_parser.parse(error_message, language=language, framework=framework)
    
            # Build search query
            search_query = error_parser.build_search_query(parsed)
    
            # Search for solutions (request more to allow for filtering)
            hits = await searcher.search(
                search_query,
                category="it",
                max_results=max_results * 2,  # Get extra results for filtering
            )
    
            # Filter and prioritize results
            if hits:
                # Filter out irrelevant sources
                irrelevant_domains = {
                    "hub.docker.com",
                    "crates.io",
                    "npmjs.com",
                    "pypi.org",
                    "pkg.go.dev",
                }
    
                filtered_hits = [
                    hit
                    for hit in hits
                    if not any(domain in hit.url.lower() for domain in irrelevant_domains)
                ]
    
                # Prioritize Stack Overflow results
                so_hits = [hit for hit in filtered_hits if "stackoverflow.com" in hit.url]
                other_hits = [hit for hit in filtered_hits if "stackoverflow.com" not in hit.url]
    
                # Combine: Stack Overflow first, then others
                hits = (so_hits + other_hits)[:max_results]
    
            if not hits:
                result = (
                    f"No solutions found for this error.\n\n"
                    f"Parsed Error Info:\n"
                    f"- Type: {parsed.error_type}\n"
                    f"- Language: {parsed.language or 'Unknown'}\n"
                    f"- Framework: {parsed.framework or 'None detected'}\n\n"
                    f"Try:\n"
                    f"- Providing more context with language/framework parameters\n"
                    f"- Searching for just the error type: {parsed.error_type}\n"
                    f"- Using web_search with broader terms"
                )
            else:
                # Format results
                lines = [
                    "Error Translation Results",
                    "═" * 70,
                    "",
                    "📋 Parsed Error Information:",
                    f"   Error Type: {parsed.error_type}",
                ]
    
                if parsed.language:
                    lines.append(f"   Language: {parsed.language.title()}")
                if parsed.framework:
                    lines.append(f"   Framework: {parsed.framework.title()}")
                if parsed.file_path:
                    location = f"{parsed.file_path}"
                    if parsed.line_number:
                        location += f":{parsed.line_number}"
                    lines.append(f"   Location: {location}")
    
                lines.extend(
                    [
                        "",
                        f"🔍 Search Query: {search_query}",
                        "",
                        "💡 Top Solutions (Stack Overflow prioritized):",
                        "─" * 70,
                        "",
                    ]
                )
    
                for idx, hit in enumerate(hits, 1):
                    # Try to extract vote count from snippet (if available)
                    votes = "N/A"
                    if hit.snippet:
                        vote_match = re.search(r"(\d+)\s*votes?", hit.snippet, re.IGNORECASE)
                        if vote_match:
                            votes = vote_match.group(1)
    
                    # Check if it's a Stack Overflow link
                    is_so = "stackoverflow.com" in hit.url
                    source_icon = "[SO]" if is_so else "[Web]"
    
                    lines.append(f"{idx}. {source_icon} {hit.title}")
                    if votes != "N/A":
                        lines.append(f"   Votes: {votes}")
                    lines.append(f"   {hit.url}")
    
                    if hit.snippet:
                        # Clean and truncate snippet
                        snippet = hit.snippet.replace("\n", " ").strip()
                        if len(snippet) > 200:
                            snippet = snippet[:200] + "..."
                        lines.append(f"   {snippet}")
    
                    lines.append("")
    
                lines.extend(
                    [
                        "─" * 70,
                        "",
                        "💡 Tips:",
                        "- Check accepted answers (marked with ✓) first",
                        "- Look for solutions with high vote counts",
                        "- Verify the solution matches your exact error",
                        "- Use crawl_url to get full answer details",
                    ]
                )
    
                result = clamp_text("\n".join(lines), MAX_RESPONSE_CHARS)
    
            success = True
    
        except Exception as exc:  # noqa: BLE001
            error_msg = str(exc)
            result = f"Error translation failed: {exc}\n\nTry simplifying the error message or provide language/framework context."
        finally:
            # Track usage
            response_time = (time.time() - start_time) * 1000
            tracker.track_usage(
                tool_name="translate_error",
                reasoning=reasoning,
                parameters={
                    "error_type": parsed.error_type if parsed else "unknown",
                    "language": language or (parsed.language if parsed else None),
                    "framework": framework or (parsed.framework if parsed else None),
                    "max_results": max_results,
                },
                response_time_ms=response_time,
                success=success,
                error_message=error_msg,
                response_size=len(result.encode("utf-8")),
            )
    
        return result
  • ErrorParser class provides helper utilities for parsing error messages: detects language/framework, extracts error type/location/key terms, cleans message, and builds optimized search queries for finding solutions. Used directly in the translate_error handler.
    class ErrorParser:
        """Parses error messages and stack traces to extract key information."""
    
        # Language detection patterns (order matters - most specific first)
        LANGUAGE_PATTERNS = {
            "rust": [
                r"error\[E\d{4}\]:",
                r"cannot borrow",
                r"--> .+\.rs:\d+:\d+",
            ],
            "typescript": [
                r"at .+\.tsx?:\d+:\d+",
                r"\.tsx?:",
                r"TS\d{4}:",
            ],
            "javascript": [
                r"at .+\.jsx?:\d+:\d+",
                r"\.jsx?:",
                r"node_modules",
                r"Cannot read property",
                r"is not defined",
            ],
            "python": [
                r"File \"(.+)\.py\"",
                r"Traceback \(most recent call last\)",
                r"(ImportError|AttributeError|ModuleNotFoundError)",
            ],
            "java": [
                r"at .+\.java:\d+",
                r"Exception in thread",
                r"(NullPointerException|IllegalArgumentException)",
            ],
            "go": [
                r"panic:",
                r"goroutine \d+",
                r".+\.go:\d+",
            ],
        }
    
        # Framework detection patterns
        FRAMEWORK_PATTERNS = {
            "react": [r"react", r"jsx", r"useState", r"useEffect"],
            "vue": [r"vue", r"@vue", r"composition-api"],
            "angular": [r"angular", r"@angular", r"ngOnInit"],
            "django": [r"django", r"django\."],
            "flask": [r"flask", r"werkzeug"],
            "fastapi": [r"fastapi", r"pydantic", r"starlette"],
            "express": [r"express", r"app\.get", r"app\.post"],
            "nextjs": [r"next", r"getServerSideProps", r"getStaticProps"],
        }
    
        # Common error patterns (checked in order - most specific first)
        ERROR_TYPE_PATTERNS = {
            "python": {
                "AttributeError": r"AttributeError: '(.+)' object has no attribute '(.+)'",
                "TypeError": r"TypeError: (.+)",
                "ImportError": r"(ImportError|ModuleNotFoundError): (.+)",
                "ValueError": r"ValueError: (.+)",
                "KeyError": r"KeyError: (.+)",
            },
            "javascript": {
                # Web-specific errors (check first - most specific)
                "CORS Error": r"CORS policy|Access-Control-Allow-Origin|No.*Access-Control",
                "Fetch Error": r"fetch.*failed|Failed to fetch|NetworkError",
                "Cannot read property": r"Cannot read propert(?:y|ies) ['\"](.+?)['\"] of",
                "undefined is not": r"undefined is not (a function|an object)",
                "null is not": r"null is not (a function|an object)",
                # Standard errors (check after specific ones)
                "TypeError": r"TypeError: (.+)",
                "ReferenceError": r"ReferenceError: (.+)",
                "SyntaxError": r"SyntaxError: (.+)",
                "RangeError": r"RangeError: (.+)",
            },
            "typescript": {
                "CORS Error": r"CORS policy|Access-Control-Allow-Origin",
                "Fetch Error": r"fetch.*failed|Failed to fetch",
                "Cannot read property": r"Cannot read propert(?:y|ies) ['\"](.+?)['\"] of",
                "TypeError": r"TypeError: (.+)",
                "ReferenceError": r"ReferenceError: (.+)",
                "SyntaxError": r"SyntaxError: (.+)",
            },
            "rust": {
                "borrow error": r"borrow of moved value",
                "cannot borrow": r"cannot borrow",
                "lifetime error": r"lifetime (.+) may not live long enough",
                "type mismatch": r"expected (.+), found (.+)",
                "E0382": r"error\[E0382\]",
                "E0502": r"error\[E0502\]",
                "E0308": r"error\[E0308\]",
            },
        }
    
        def parse(
            self,
            error_message: str,
            language: str | None = None,
            framework: str | None = None,
        ) -> ParsedError:
            """
            Parse an error message to extract key information.
    
            Args:
                error_message: The error text or stack trace
                language: Programming language (auto-detected if None)
                framework: Framework name (auto-detected if None)
    
            Returns:
                ParsedError with extracted information
            """
            # Detect language if not provided
            if not language:
                language = self._detect_language(error_message)
    
            # Detect framework if not provided
            if not framework:
                framework = self._detect_framework(error_message)
    
            # Extract error type
            error_type = self._extract_error_type(error_message, language)
    
            # Extract file path and line number
            file_path, line_number = self._extract_location(error_message)
    
            # Extract key terms
            key_terms = self._extract_key_terms(error_message, error_type)
    
            # Clean message
            message = self._clean_message(error_message)
    
            return ParsedError(
                error_type=error_type or "Unknown Error",
                message=message,
                language=language,
                framework=framework,
                file_path=file_path,
                line_number=line_number,
                key_terms=key_terms,
            )
    
        def _detect_language(self, text: str) -> str | None:
            """Detect programming language from error message."""
            scores = {}
            for lang, patterns in self.LANGUAGE_PATTERNS.items():
                score = sum(1 for pattern in patterns if re.search(pattern, text, re.IGNORECASE))
                if score > 0:
                    scores[lang] = score
    
            if scores:
                return max(scores, key=scores.get)
            return None
    
        def _detect_framework(self, text: str) -> str | None:
            """Detect framework from error message."""
            text_lower = text.lower()
    
            for framework, patterns in self.FRAMEWORK_PATTERNS.items():
                if any(re.search(pattern, text_lower) for pattern in patterns):
                    return framework
            return None
    
        def _extract_error_type(self, text: str, language: str | None) -> str | None:
            """Extract the error type/name."""
            # Check for common web errors first (language-agnostic)
            web_error_patterns = {
                "CORS Error": r"CORS policy|Access-Control-Allow-Origin|No.*Access-Control",
                "Fetch Error": r"fetch.*failed|Failed to fetch|NetworkError",
                "Cannot read property": r"Cannot read propert(?:y|ies) ['\"](.+?)['\"] of",
            }
    
            for error_name, pattern in web_error_patterns.items():
                if re.search(pattern, text, re.IGNORECASE):
                    return error_name
    
            # Language-specific extraction if language is detected
            if language and language in self.ERROR_TYPE_PATTERNS:
                for error_name, pattern in self.ERROR_TYPE_PATTERNS[language].items():
                    if re.search(pattern, text, re.IGNORECASE):
                        return error_name
    
            # Generic error type extraction as fallback
            match = re.search(r"([\w]+Error|[\w]+Exception):", text)
            if match:
                return match.group(1)
    
            return None
    
        def _extract_location(self, text: str) -> tuple[str | None, int | None]:
            """Extract file path and line number."""
            # Python format: File "path.py", line 123
            match = re.search(r'File "(.+?)", line (\d+)', text)
            if match:
                return match.group(1), int(match.group(2))
    
            # JavaScript/TypeScript format: at path.js:123:45
            match = re.search(r"at (.+?):(\d+):\d+", text)
            if match:
                return match.group(1), int(match.group(2))
    
            # Rust format: --> path.rs:123:45
            match = re.search(r"--> (.+?):(\d+):\d+", text)
            if match:
                return match.group(1), int(match.group(2))
    
            return None, None
    
        def _extract_key_terms(self, text: str, error_type: str | None) -> list[str]:
            """Extract key terms for searching."""
            terms = set()  # Use set to avoid duplicates
    
            # Important web/tech terms to always capture
            important_terms = [
                "CORS",
                "cors",
                "fetch",
                "async",
                "await",
                "Promise",
                "undefined",
                "null",
                "map",
                "filter",
                "reduce",
                "Access-Control-Allow-Origin",
                "XMLHttpRequest",
                "module",
                "import",
                "export",
                "require",
            ]
    
            # Extract important terms first
            text_lower = text.lower()
            for term in important_terms:
                if term.lower() in text_lower:
                    terms.add(term)
                    if len(terms) >= 3:  # Limit important terms to 3
                        break
    
            # Extract quoted strings (often property names or specific values)
            quoted = re.findall(r"'([^']+)'|\"([^\"]+)\"", text)
            for match in quoted:
                term = match[0] or match[1]
                # Keep short important terms, ignore paths
                if term and "/" not in term and "\\" not in term:
                    # Allow short terms for property names like "map", "id", etc.
                    if len(term) <= 15:  # Reasonable property name length
                        if not error_type or term.lower() != error_type.lower():
                            terms.add(term)
                            if len(terms) >= 5:
                                break
    
            # Extract technical terms (CamelCase, snake_case)
            technical = re.findall(r"\b[A-Z][a-z]+(?:[A-Z][a-z]+)+\b|\b\w+_\w+\b", text)
            # Don't exclude undefined/null - they're useful search terms
            for term in technical:
                if not error_type or term != error_type:
                    terms.add(term)
                    if len(terms) >= 5:
                        break
    
            return list(terms)[:5]  # Return max 5 unique key terms
    
        def _clean_message(self, text: str) -> str:
            """Clean and extract the core error message."""
            # Try to find the main error line
            lines = text.strip().split("\n")
    
            # Look for the error line (usually contains "Error:" or "Exception:")
            for line in reversed(lines):
                if re.search(r"(Error|Exception):", line):
                    return line.strip()
    
            # If no error line found, return first non-empty line
            for line in lines:
                if line.strip():
                    return line.strip()
    
            return text.strip()
    
        def build_search_query(self, parsed: ParsedError) -> str:
            """Build an optimized search query from parsed error."""
            parts = []
    
            # Add language
            if parsed.language:
                parts.append(parsed.language)
    
            # Add framework
            if parsed.framework:
                parts.append(parsed.framework)
    
            # Add error type
            if parsed.error_type and parsed.error_type != "Unknown Error":
                parts.append(parsed.error_type)
    
            # Add key terms (limit to avoid overly specific queries)
            parts.extend(parsed.key_terms[:2])
    
            # Build query - don't use site filter as SearXNG handles this better
            # with its category-based engine selection
            query = " ".join(parts)
    
            # Add "error" or "fix" to help guide results
            if query:  # Only add if we have content
                query += " error fix"
    
            return query
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure and does so effectively. It describes key behavioral traits: automated language/framework detection, extraction of key error information, searching for solutions ranked by votes and relevance, and returning solutions with code examples. The only minor gap is lack of information about rate limits, authentication needs, or potential costs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and appropriately sized. It begins with a clear purpose statement, follows with behavioral details, provides usage guidance in a bulleted 'Perfect for' section, and concludes with concrete examples. Every sentence adds value, with no redundant information or wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (5 parameters, automated detection features) and the presence of an output schema (which means return values don't need explanation), the description is remarkably complete. It covers purpose, behavior, usage scenarios, and parameter semantics thoroughly. The only potential gap is lack of information about search limitations or source freshness, but this is minor given the overall completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description must compensate and does so excellently. It explains the core 'error_message' parameter's purpose and provides three detailed examples showing how to use all parameters (error_message, reasoning, language, framework). The examples demonstrate parameter usage in realistic scenarios, adding substantial meaning beyond what the bare schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('find solutions for error messages and stack traces') and resources ('from Stack Overflow and GitHub'). It distinguishes itself from sibling tools like 'search_examples' or 'web_search' by focusing specifically on error resolution with automated language/framework detection and solution ranking.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool through the 'Perfect for:' section, which lists four specific scenarios (debugging production errors, understanding cryptic messages, finding code fixes, learning from similar issues). It also includes three concrete examples that demonstrate appropriate use cases, though it doesn't explicitly state when NOT to use it or mention alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/elad12390/web-research-assistant'

If you have feedback or need assistance with the MCP directory API, please join our Discord server