Skip to main content
Mark function return values that should not be ignored, ensuring important results are used and errors are properly handled.

Syntax

---@nodiscard [reason]

Purpose

The @nodiscard annotation:
  • Enforces error handling for critical operations
  • Prevents silently ignoring important return values
  • Improves code safety and reliability
  • Generates warnings when return values are discarded

Examples

Basic Usage

---@nodiscard
---@return boolean success
function validateInput(input)
    return input ~= nil and input ~= ""
end

With Reason

---@nodiscard Must check for errors
---@param data string JSON data
---@return table? parsed_data
---@return string? error_message
function parseJSON(data)
    local success, result = pcall(json.decode, data)
    if success then
        return result, nil
    else
        return nil, result
    end
end

Critical Operations

---@nodiscard Critical: File operation result must be checked
---@param filepath string File path
---@param content string Content to write
---@return boolean success
---@return string? error
function writeFileSecure(filepath, content)
    local file, err = io.open(filepath, "w")
    if not file then
        return false, err
    end

    local success, writeErr = pcall(file.write, file, content)
    file:close()

    if not success then
        return false, writeErr
    end

    return true, nil
end

Database Operations

---@nodiscard Database errors must be handled
---@param query string SQL query
---@return table[] results
---@return string? error
function executeQuery(query)
    local results, error = database.execute(query)
    if error then
        return {}, error
    end
    return results, nil
end

Memory Allocation

---@nodiscard Memory allocation may fail
---@param size number Buffer size
---@return buffer? buffer
function allocateBuffer(size)
    if size <= 0 or size > MAX_BUFFER_SIZE then
        return nil
    end
    return buffer.create(size)
end

Good vs Bad Usage

Good: Result is Checked

local isValid = validateInput(userInput)
if not isValid then
    print("Invalid input")
end

Good: Error Handling

local data, error = parseJSON(jsonString)
if error then
    print("Parse error:", error)
    return
end
-- Safely use data
print(data.name)

Good: File Operation Checked

local success, writeError = writeFileSecure("output.txt", "data")
if not success then
    print("Write failed:", writeError)
    return
end

Bad: Ignoring Return Value

-- These will trigger warnings:
validateInput(userInput)  
-- Warning: Return value should not be discarded

parseJSON(jsonString)     
-- Warning: Must check for errors

writeFileSecure("test.txt", "content")  
-- Warning: Critical: File operation result must be checked

Common Use Cases

Validation Functions

---@nodiscard Validation result must be checked
---@param email string Email address
---@return boolean is_valid
---@return string? error_message
function validateEmail(email)
    if not email:match("^[%w.]+@[%w.]+%.[%a]+$") then
        return false, "Invalid email format"
    end
    return true, nil
end

Resource Acquisition

---@nodiscard Resource acquisition may fail
---@param config table Connection config
---@return Connection? connection
---@return string? error
function acquireConnection(config)
    local conn, err = Connection.new(config)
    if not conn then
        return nil, err
    end
    return conn, nil
end

State Checks

---@nodiscard State must be verified before proceeding
---@return boolean is_ready
function isSystemReady()
    return systemState == "ready" and not hasErrors()
end

Transaction Results

---@nodiscard Transaction result must be verified
---@param amount number Transaction amount
---@return boolean success
---@return string? transaction_id
---@return string? error
function processPayment(amount)
    local result = paymentGateway.charge(amount)
    if result.success then
        return true, result.id, nil
    else
        return false, nil, result.error
    end
end

Best Practices

  1. Use for error-returning functions: Always mark functions that return errors
  2. Provide clear reasons: Explain why the return value is important
  3. Return multiple values: Use Lua’s multiple return values for results and errors
  4. Document thoroughly: Explain what each return value means
  5. Be consistent: Apply to all similar critical operations
Ignoring @nodiscard return values can lead to unhandled errors, data corruption, or security vulnerabilities. Always check these returns.
Combine @nodiscard with proper error handling patterns (multiple return values) for robust error management.

Features

Error Enforcement

Enforce proper error handling

Custom Messages

Provide context-specific warnings

IDE Integration

Get warnings directly in your editor

Safety Guarantees

Prevent silent failures

Build docs developers (and LLMs) love