lovr.errhand

The lovr.errhand callback is run whenever an error occurs. It receives a parameter containing the error message. It should return a handler function that will run in a loop to render the error screen.

This handler function is of the same type as the one returned by lovr.run and has the same requirements (such as pumping events). If an error occurs while this handler is running, the program will terminate immediately -- lovr.errhand will not be given a second chance. Errors which occur in the error handler or in the handler it returns may not be cleanly reported, so be careful.

A default error handler is supplied that renders the error message as text to the headset and to the window.

function lovr.errhand(message)
  -- your code here
end

Arguments

NameTypeDescription
messagestring The error message.

Returns

NameTypeDescription
handlerfunction The error handler function. It should return nil to continue running, "restart" to restart the app, or a number representing an exit status.

Example

The default error handler.

function lovr.errhand(message)
  local function formatTraceback(s)
    return s:gsub('\n[^\n]+$', ''):gsub('\t', ''):gsub('stack traceback', '\nStack')
  end

  message = tostring(message) .. formatTraceback(debug.traceback('', 4))
  print('Error:\n' .. message)

  if not lovr.graphics or not lovr.graphics.isInitialized() then
    return function() return 1 end
  end

  if lovr.audio then lovr.audio.stop() end

  local scale = .35
  local font = lovr.graphics.getDefaultFont()
  local wrap = .7 * font:getPixelDensity()
  local lines = font:getLines(message, wrap)
  local width = math.min(font:getWidth(message), wrap) * scale
  local height = .8 + #lines * font:getHeight() * scale
  local x = -width / 2
  local y = math.min(height / 2, 10)
  local z = -10

  lovr.graphics.setBackgroundColor(.11, .10, .14)
  font:setPixelDensity()

  local function render(pass)
    pass:setColor(.95, .95, .95)
    pass:text('Error', x, y, z, scale * 1.6, 0, 0, 0, 0, nil, 'left', 'top')
    pass:text(message, x, y - .8, z, scale, 0, 0, 0, 0, wrap, 'left', 'top')
  end

  return function()
    lovr.event.pump()

    for name, a in lovr.event.poll() do
      if name == 'quit' then return a or 1
      elseif name == 'restart' then return 'restart', lovr.restart and lovr.restart()
      elseif name == 'keypressed' and a == 'f5' then lovr.event.restart() end
    end

    if lovr.headset and lovr.headset.getDriver() ~= 'desktop' then
      lovr.headset.update()
      local pass = lovr.headset.getPass()
      if pass then
        render(pass)
        lovr.graphics.submit(pass)
        lovr.headset.submit()
      end
    end

    if lovr.system.isWindowOpen() then
      local pass = lovr.graphics.getWindowPass()
      if pass then
        render(pass)
        lovr.graphics.submit(pass)
        lovr.graphics.present()
      end
    end
  end
end

See also