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

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

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