{"id":27946811,"url":"https://github.com/dmccuskey/lua-error","last_synced_at":"2025-05-07T13:58:05.390Z","repository":{"id":24693785,"uuid":"28105040","full_name":"dmccuskey/lua-error","owner":"dmccuskey","description":"Robust error handling for Lua (try(), catch(), and finally() .... finally!)","archived":false,"fork":false,"pushed_at":"2015-05-11T08:51:22.000Z","size":324,"stargazers_count":18,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-07T13:57:59.256Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dmccuskey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-12-16T20:25:07.000Z","updated_at":"2025-03-23T09:23:55.000Z","dependencies_parsed_at":"2022-08-17T17:01:11.038Z","dependency_job_id":null,"html_url":"https://github.com/dmccuskey/lua-error","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmccuskey%2Flua-error","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmccuskey%2Flua-error/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmccuskey%2Flua-error/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmccuskey%2Flua-error/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dmccuskey","download_url":"https://codeload.github.com/dmccuskey/lua-error/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252892523,"owners_count":21820647,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-07T13:58:04.647Z","updated_at":"2025-05-07T13:58:05.382Z","avatar_url":"https://github.com/dmccuskey.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"## lua-error ##\n\nRobust error handling for Lua which features:\n\n* `try()`, `catch()`, `finally()` functions\n* custom error objects\n\n\n### Quick ###\n\n```lua\n-- import creates a base Error class and global funcs try(), catch(), finally()\n\nlocal Error = require 'lua_error'\n\n\n-- do this anywhere in your code:\n\ntry{\n  function()\n    -- make a call which could raise an error\n  end,\n  \n  catch{\n    function( err )\n      -- handle the error\n    end\n  },\n  \n  finally{\n    function()\n      -- do some cleanup\n    end\n  }\n}\n```\n\n\u003e Note: the `catch{}` and `finally{}` are optional.\n\n\n\n### Overview ###\n\nThe library is a culmination of several ideas found on the Internet put into a cohesive package. It was also inspired by the error handling in Python. (see References below)\n\nThere are two different components to this library which can either be used together or independently:\n\n1. *Gobal functions*: `try`, `catch`, and `finally` which give structure\n2. *Error object class*: which can be used by itself or subclassed for more refined errors\n\n\n#### Lua Errors ####\n\nThe basic pieces of error handling built into Lua are the functions `error()` and `pcall()`. We only need to focus on `error()`, since that's what we use to raise an error condition in a program, like so:\n\n```lua\nerror( \"this is my error\" )\n```\n\nthat in turn will create something like this:\n\n```\nmy_lua_file.lua:17: this is my error\nstack traceback:\n\t[C]: in function 'error'\n\t/path_to_file/my_lua_file.lua:17: in main chunk\n\t[C]: in function 'require'\n\t?: in function 'require'\n\t/path_to_file/main.lua:104: in function 'main'\n\t/path_to_file/main.lua:110: in main chunk\n```\n\nIn the error we can see our error string \"`this is my error`\" and the corresponding traceback.\n\nAs shown in our simple example, `error()` is often only used to create string-type errors. There are a couple of drawbacks to these types of errors in that they are:\n\n1. they are fragile\n\n  Is that string \"`ProtocolError`\" from my module or yours? If string \"`out of data`\" changes then my code will break\n\n2. they are harder to represent other, finer-grained errors\n\n  Like `error.overflow`, `app.error.protocol`, etc\n\nThough one feature of `error()` which can help is that its argument can be anything, not just a string, so later we'll give it some Error objects.\n\n\n#### try(), catch(), finally() ####\n\nThis function trio is the backbone of awesome error handling. The following is the basic structure using all three of the functions.\n\n\u003e Note: in the example below, `\u003cfunc ref\u003e` represents a function reference, for example: \n\u003e\n\u003e `local func_ref = function() end`\n\n```lua\ntry{\n  \u003cfunc ref\u003e,\n  \n  catch{\n    \u003cfunc ref\u003e\n  },\n  \n  finally{\n    \u003cfunc ref\u003e\n  }\n}\n```\n\nThis format works because it takes advantage of Lua's dual-way to call functions, eg:\n\n`hello()` or `hello{}`, the latter being equivalent to `hello( {} )`\n\nSo essentially this format is really a function `try()` which accepts a single `array` argument containing up to _three_ function references like so, `{ \u003cfunc ref\u003e, catch{}, finally{} }`.\n\nKeep in mind that the terms `catch` and `finally` are themselves global functions just like `try`, and like `try` these each take a single `array` argument but contain only a single function like so `{ \u003cfunc ref\u003e }`.\n\n\nHere are some alternate layouts showing the same thing:\n\n```lua\nflattened out:\ntry{ \u003cfunc ref\u003e, catch{ \u003cfunc ref\u003e }, finally{ \u003cfunc ref\u003e } }\n\nsame thing, including parens:\ntry({ \u003cfunc ref\u003e, catch({ \u003cfunc ref\u003e }), finally({ \u003cfunc ref\u003e }) })\n```\n\n\n#### Custom Errors ####\n\nThe objects in this framework use [`lua-objects`](https://github.com/dmccuskey/lua-objects) as the backbone.\n\nHere's a quick example how to create a custom error type:\n\n```lua\n-- import module\nlocal Error = require 'lua_error'\n\n-- create custom error class\n-- this class could be more complex,\n-- but this is all we need for a custom error\nlocal ProtocolError = newClass( Error, { name=\"Protocol Error\" } )\n\n-- raise an error\nerror( ProtocolError( \"bad protocol\" ) )\n```\n\nFor more examples of custom errors, you can check out the unit tests or the projects [`dmc-wamp`](https://github.com/dmccuskey/dmc-wamp), [`lua-bytearray`](https://github.com/dmccuskey/lua-bytearray), etc.\n\n\n\n#### Example ####\n\nThe following code snippet is a real-life example taken from [`dmc-wamp`](https://github.com/dmccuskey/dmc-wamp):\n\n```lua\n\ttry{\n\t\tfunction()\n\t\t\tself._session:onOpen( { transport=self } )\n\t\tend,\n\n\t\tcatch{\n\t\t\tfunction(e)\n\t\t\t\tif type(e)=='string' then\n\t\t\t\t\terror( e )\n\t\t\t\telseif e:isa( Error.ProtocolError ) then\n\t\t\t\t\tprint( e.traceback )\n\t\t\t\t\tself:_bailout{\n\t\t\t\t\t\tcode=WebSocket.CLOSE_STATUS_CODE_PROTOCOL_ERROR,\n\t\t\t\t\t\treason=\"WAMP Protocol Error\"\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tprint( e.traceback )\n\t\t\t\t\tself:_bailout{\n\t\t\t\t\t\tcode=WebSocket.CLOSE_STATUS_CODE_INTERNAL_ERROR,\n\t\t\t\t\t\treason=\"WAMP Internal Error ({})\"\n\t\t\t\t\t}\n\t\t\t\tend\n\t\t\tend\n\t\t}\n\t}\n```\n\nIn the `catch` you see that:\n* first, we're checking to see if it's a regular string-type error. if so, re-raise the error since we only care about Error objects.\n* second, by using the method `isa`, see if the error is type `ProtocolError`, bailout with protocol error.\n* third, it's not an error we can handle, so bailout with an internal error.\n\n\n###References###\n\n* https://gist.github.com/cwarden/1207556\n* http://www.lua.org/pil/8.4.html\n* http://www.lua.org/wshop06/Belmonte.pdf\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmccuskey%2Flua-error","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdmccuskey%2Flua-error","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmccuskey%2Flua-error/lists"}