Good First Issues in Elixir
Explore curated starter issues in high-scoring Elixir repositories. Every listed issue belongs to a welcoming repository scored by C-Rankβ’ on PR merge rates, review responsiveness, and first-timer acceptance.
Arm Issue Sniper for fresh Elixir beginner issues
Beginner issues in welcoming S/A-Tier repositories get snatched within 15 minutes. Receive instant alerts on Discord, Telegram, or Email the minute a maintainer opens a new task.
Live Good First Issues (30)
Real-Time Open GitHub IssuesThis issue is to audit the Engine code, and remove any unnecessary code that increases its size. The Engine gets compiled for each toolchain combination the user needs, so the larger the engine the longer it takes to compile on the fly, and the more disk space it needs to cache those engine builds. Besides that, the Engine was always intended to be small. Things to check: Dead code Forge code that is only used by Expert and never by the Engine (that is, Forge should contain only the code shared by Expert and Engine, whenever possible) Functionality implemented in the Engine that could live in the Expert app instead
Code of Conduct I agree to follow this project's Code of Conduct AI Policy I agree to follow this project's AI Policy, or I agree that AI was not used while creating this issue. Versions Elixir 1.19.6 Erlang 28.5.0.7 ash 3.33.9 ash_postgres 2.13.1 ash_sql 0.7.6 Operating system macOS, Linux (Debian Trixie) Current Behavior Given resource Profile in database schema & table schema_containing_profiles.profiles and resource Report in database schema & table schema_containing_reports.reports when I use an expression with a resource-based inline aggregate in a calculation of Profile to select a field from Report the calculation fails at runtime because the generated SQL tries to select from schema_containing_profiles.reports. Reproduction Probably all of the examples given in the Resource-based Inline Aggregates docs will fail when using data_layer: AshPostgres.DataLayer in both resources and different schemas, f.i. schema "schema_containing_profiles" and schema "schema_containing_repo
Problem With config.broadcast.ack: true, a client that sends a broadcast on a private channel waits for the server to reply. When an RLS write policy denies the broadcast, or the broadcast fails on the server, Realtime never replies. The push times out, and supabase-js resolves send() with 'timed out' instead of 'error': https://github.com/supabase/supabase-js/blob/54c225dacb1fc5f5a0a97c93908a46b7e8f5c9cc/packages/core/realtime-js/src/RealtimeChannel.ts#L1119-L1125 A denied write looks like a network problem, so people debug latency instead of their policies. BroadcastHandler.handle/3 returns {:noreply, socket} regardless of ack_broadcast when the write policy denies the message and in every error clause: realtime/lib/realtime_web/channels/realtime_channel/broadcast_handler.ex Lines 80 to 104 in a3591b3 {:ok, policies} -> {:noreply, assign(socket, :po
Problem Subscriptions.delete_all/1 runs delete from realtime.subscription; without checking that the table exists: realtime/lib/extensions/postgres_cdc_rls/subscriptions.ex Lines 163 to 173 in a85489e @spec delete_all(conn()) :: :ok def delete_all(conn) do Logger.debug("Delete all subscriptions") case query(conn, "delete from realtime.subscription;", []) do {:ok, _} -> :ok {:error, reason} -> log_error("SubscriptionDeletionFailed", reason) end catch :exit, reason -> log_error("SubscriptionDeletionFailed", {
Versions: ash_ai 1.0.3, ash 3.33.3, plug 1.20.3, Elixir 1.20.1 on OTP 29. Present on the default branch at 158d5e9 (checked 2026-09-15). Found by an AI assistant working with a human who was fuzz-testing their own application; reproduced in a minimal project with default settings. Request AshAi.Mcp.Router with tools: [:read_posts], called with Plug.Test as ash_ai's own tests do (the router runs its own Plug.Parsers). "Initialize-based path": no MCP-Protocol-Version header and no _meta (a header naming an earlier revision selects it too). "2026-07-28 path": header MCP-Protocol-Version: 2026-07-28 and _meta in params. Body initialize-based path 2026-07-28 path a batch array, [] or [{"jsonrpc":"2.0","id":1,"method":"tools/list"}] raises FunctionClauseError in AshAi.Mcp.Server.parse_json_rpc/1 clean -32600 "params": "x" on tools/call or initialize (tools/list ignores params and answers 200) raises FunctionClauseError in Access.get/3 raises, for every method with an id "params":
Versions: ash_postgres 2.13.1, ash_sql 0.7.5, ash 3.33.3, ecto 3.14.2, postgrex 0.22.4, PostgreSQL 18.6, Elixir 1.20.1 on OTP 29. Present on the default branch at 97ffea9 (checked 2026-09-15). Found by an AI assistant working with a human who was fuzz-testing their own application; reproduced in a minimal project with default settings. Request With a UUID primary key and query = Ash.Query.filter(Post, id == "not-a-uuid"), Ash.read(query) returns {:error, %Ash.Error.Invalid{errors: [%Ash.Error.Query.InvalidFilterValue{}]}}. These do not: Case Call Result a Ash.count(query), Ash.exists(query), Ash.aggregate(query, {:m, :max, field: :inserted_at}) raises Ecto.Query.CastError b query |> Ash.Query.limit(1) |> Ash.count() raises Ecto.SubQueryError c Post |> Ash.Query.load(comments: Comment |> Ash.Query.filter(id == "not-a-uuid") |> Ash.Query.limit(1)) |> Ash.read() with two or more posts raises Ash.Error.Unknown wrapping Ecto.SubQueryError d Post |> Ash.Query.filter_input(%{comm
Versions: ash_postgres 2.13.1, ash_sql 0.7.5, ash 3.33.3, ecto 3.14.2, postgrex 0.22.4, PostgreSQL 18.6, Elixir 1.20.1 on OTP 29. Present on the default branch at 97ffea9 (checked 2026-09-15). Found by an AI assistant working with a human who was fuzz-testing their own application; reproduced in a minimal project with default settings. Request A title containing a NUL byte (0x00): Ash.create(Post, %{title: "a" <> <<0>> <> "b"}) and Post |> Ash.Query.filter(title == "a" <> <<0>> <> "b") |> Ash.read(). Through AshJsonApi: POST /posts with that title and GET /posts?filter[title]=a%00b. Through AshGraphql: createPost with the value as a variable or as a \u0000 escape. Through ash_lua: blog.post.create with a Lua string literal containing the byte. Observed The server rejects the value and the error is returned as unknown-class: {:error, %Ash.Error.Unknown{errors: [%Ash.Error.Unknown.UnknownError{error: "** (Postgrex.Error) ERROR 22021 (character_not_in_repertoire) invalid byte sequence f
Versions: ash 3.33.3, Elixir 1.20.1 on OTP 29. Present on the default branch at a7a5105 (checked 2026-09-15). Found by an AI assistant working with a human who was fuzz-testing their own application; reproduced in a minimal project with default settings. Request On a read action with pagination keyset?: true, offset?: true: Ash.read(Post, page: [after: "x", offset: 1]); also page: [limit: 0], [limit: -1], [limit: "x"], [limit: 1, offset: -1]. Through AshJsonApi: GET /posts?page[after]=x&page[offset]=1. And Ash.read(Post, page: "x"). Observed {:error, %Ash.Error.Unknown{errors: [%Ash.Error.Unknown.UnknownError{error: "** (Spark.Options.ValidationError) invalid value for :page option: unknown options [:offset], valid options are: [:before, :after, :limit, :filter, :count]"}]}} (expected positive integer, got: 0 and so on for the others.) JSON:API answers 500. page: "x" raises FunctionClauseError in Access.get/3. By contrast page: [after: "x", limit: 1] returns Ash.Error.Invalid with A
https://github.com/oliver-kriska/claude-elixir-phoenix https://github.com/danielbergholz/phoenix-ai-setup Any other good examples?
at the bottom of Home dashboard there is this section called "Polls closing soon" that has a button labeled Refresh. I clicked it and got this toast with the text "Polls have been reset" which makes no sense to me. https://campground.bonfire.cafe on 1.0.7-rc.4
Session stopped 1.1s after a second abrupt disconnect, instead of 30s. Join a matchmaking queue, drop the connection, reconnect, drop again inside 30s. The connection_timeout armed by the first drop is never cancelled when the player reconnects. It fires 30s later, finds conn_pid nil from the second drop, and stops a session that had already reconnected. The timer armed by the second drop still had 29s to run. Tagged each armed timer with temporary logging to get this: 19:24:53.705 CT_ARM id=4 fires_in=30000ms user=3 19:25:03.757 CT_RECONNECT matchmaking={:searching, joined_queues: [{"1v1", "30009617"}]} 19:25:22.590 CT_ARM id=6 fires_in=30000ms user=3 19:25:23.707 CT_FIRE id=4 conn_pid=nil matchmaking={:searching, ...} decision=STOP 19:25:23.704 Player timed out, stopping session Takes party and battle state with it. Paired players get matchmaking/lost when it happens mid-pairing. Three places arm it (session.ex:584, :1680, :1777), all discarding the ref, and :timer.cancel is
Support scripts has no way to tell whether it was recently modified and what was modified, making it a little more difficult to debug issues. When a script results in an error, it sometimes leads to an investigation of whether the support script was changed/broken or if a device's firmware changed. But It would be nice to have: A section for "last edited at: " or something similar. A way to see previous versions of the support script, so rollbacks can be easy.
When writing support scripts, I am unsure if the script has errors until I actually try running it. To combat this, I tend to write the code on an IDE with a LSP/linter first, and then paste it in. It would be nice if I can get feedback in the app without having to leave it and open an IDE. This would make support scripts faster to write, and reduce the risk of a bad script reaching the device.
Currently when you reset password, it removes 2FA. That should be changed to requiring to input the 2FA code, if enabled
If a raw type banned phrase contains a 1, 3, 4, 5, 7, 8, 0, - or _ it will never match any text because those characters will be replaced by Teiserver.Helper.StringHelper.leet_replace before the text is passed to message_severity check in Teiserver.Chat.WordLib.blacklisted_phrase?. def blacklisted_phrase?(text) do text = StringHelper.leet_replace(text) # If it's a high severity match then yes it is blacklisted BannedPhrase.message_severity(text, :high) == :high end def leet_replace(title) do title |> String.downcase() |> String.replace("1", "l") |> String.replace("3", "e") |> String.replace("4", "a") |> String.replace("5", "s") |> String.replace("7", "t") |> String.replace("8", "b") |> String.replace("0", "o") |> String.replace("-", "") |> String.replace("_", "") end
Steps to reproduce: Go to any users admin page (teiserver/admin/user/) Click actions dropdown and select reset flood protection Not Found
New data expected for that event: beyond-all-reason/tachyon#150 so that client can know which state they're in wrt matchmaking.
Currently the page has an "Ignore users already banned" checkbox that filters already banned users. A similar checkbox is requested to ignore users that were assigned the "Trusted" role. Default enabled.
The current columns are "Name", "Domain", "Client", "Status", "Winrate", "Recents", "Play time", "games allied", "games vs", "mac", "sysinfo", "client", "hw1", "hw2", "hw3", "hw4", "ip", "Last login", "Registered". This is a request to allow sorting (re-ordering) the returned list by the columns "Name" (alphabetically), "Status", "Play time" (highest first), "games allied" (highest first), "games vs" (highest first), "mac", "sysinfo", "client", "hw1", "hw2", "hw3", "hw4", "Last login" (newest first, default sort), "Registered" (newest first). Sorting "Domain" by email domain (e.g. @gmail.com) would be useful but not necessary depending on the difficulty of implementation.
The current columns are "New user", "Status", "Last login", "Registered", "Duel", "FFA", "Team". This is a request to allow sorting (re-ordering) the returned list by the columns "New user" (alphabetically), "Last login" (newest first, default sorting), "Registered" (newest first)
Currently when reporting a friend, you're getting an message that you can not report a friend and that the report has not been submitted. The desired result should remove that limitation to allow the reporting of friends
Context We have used 3rd party code quality badges e.g. CodeClimate in the past. But haven't applied them to our Elixir projects ... until now! π€·ββοΈ Example while reading: https://github.com/cesium/safira discovered via @ruilopesm & @nelsonmestevao π«Ά we see they have the following badge: prominently displayed: The action is: /cesium/safira/.github/workflows/style.yml Note: we are using credo in several projects e.g: mvp just not running the mix task on GitHub Actions or displaying a badge for "Code Quality". Todo β Document the setup steps in a code-style.md file in this (/learn-elixir) repo. π Create PR here in /learn-elixir π Add it to at least one repo, e.g: fields π» Run the mix credo --all --strict on localhost to ensure it passes; π» Make any necessary changes. π οΈ Add a flat-square badge to the repo. π·οΈ Create PR in the repo where the style.yml task is being added. Submit for review. π
There's no such thing as "free" Apps on Heroku anymore ... π€¦ββοΈ https://phoenix-content-negotiation.herokuapp.com/.json I don't have time to address this right now ... β³ But I am going to remove the link from the repo: Just so we aren't sending anyone there. π« Todo Deploy a simple quotes app to Fly.io that displays a quote Curate a few unsplash backgrounds: https://unsplash.com/s/photos/nature-background e.g: https://unsplash.com/photos/green-mountains-and-green-trees-beside-river-under-blue-sky-during-daytime-vK26p2SFX3E https://unsplash.com/photos/green-trees-on-green-grass-field-under-blue-sky-and-white-clouds-during-daytime-OJ02cQHePds Stretch Goal: use tags to display a background image that is relevant to the quote.
Motivation We have the space there and it gives us a way to see everything at one glance as well as a possibility to jump to each one. Current UI Proposed UI
Running: SELECT count(*) AS exact_count FROM hits; We see: With 30M Rows. This query takes 244 seconds. β³ Running this query for each hit badge was crashing the server. π But with the hit_count table in place, it's now not a burning issue π₯ π₯ priority-2 because the aggregation isn't crashing the server anymore and we can fix this with time. π§βπ» π Starting point: https://stackoverflow.com/questions/55018986/postgresql-select-count-query-takes-long-time
Getting the following error: 08:51:46 ** (exit) an exception was raised: 08:51:46 ** (Ecto.MultipleResultsError) expected at most one result but got 2 in query: 08:51:46 from h0 in Hits.HitCount, 08:51:46 (ecto 3.13.6) lib/ecto/repo/queryable.ex:166: Ecto.Repo.Queryable.one/3 08:51:46 (hits 1.7.14) lib/hits_web/controllers/hit_controller.ex:48: HitsWeb.HitController.index/2 08:51:46 (hits 1.7.14) lib/hits_web/controllers/hit_controller.ex:1: HitsWeb.HitController.phoenix_controller_pipeline/2 08:51:46 (hits 1.7.14) lib/hits_web/endpoint.ex:1: HitsWeb.Endpoint.plug_builder_call/2 https://fly.io/apps/hits/monitoring Should be quick to fix in the query. π BRB. π§βπ»
Part of the Graduations epic. Goal Validate raxol_symphony (pre-alpha) against a real Linear/GitHub repo, then reserve/cut its first Hex release. Context raxol_symphony is an OTP port of OpenAI Symphony: a tracker-driven coding-agent orchestrator (Orchestrator BaseManager polls Memory/Linear/GitHub, claims eligible issues, isolates each in a per-issue workspace, runs a coding agent to terminal state). Two runners (Runners.RaxolAgent, Runners.Codex), six surfaces via PubSub, evidence framework. Full description in CLAUDE.md (Symphony section) + HANDOVER.md. Scope Live validation against a real Linear / GitHub repo (drive real issues through to PRs). Orchestrator integration of the parallel GraphAdapter (workflow_mode: :graph_parallel); per-branch pause + compensate (see TODO.md "Symphony" open items). SSH worker dispatch (worker.ssh_hosts, one-worker-lifetime-per-host). Cache wiring for the Session-backed runner (~30 min, same opt-in pattern). Hex reservation/release once a live r
Part of the Graduations epic. Human-in-the-loop / funds required for the final live step. Goal Take raxol_acp (0.2.0, pre-alpha) to its first live Base-mainnet offering, then cut the first Hex release. Context raxol_acp is code-complete on the v2 hook/event model against the deployed Base contracts (v1 memo model retired). Full state in HANDOVER.md (top ACP entries) and CLAUDE.md. The single mainnet target is xochi_cross_chain_transfer (pure-relay storefront: raxol never touches transfer funds, takes an ACP fee; the buyer signs the Xochi intent, Riddler settles). Scope (an agent prepares; a human executes the funded steps) SCA :live_bundler end-to-end: real EntryPoint, empty-callData deploy sponsorship, installed? getter selector; SolverAgent-vs-Base-staging run (see TODO.md open items). Item-4 A-path live gate Base->Tron (needs funds + Riddler RELAY_GASLESS_PULL_ENABLED; ERC-3009 blocked on Riddler#159); verify checkpoint kill-and-resume. Graduate the offering: live run on Base ma
Part of the Hermes Fast-Follow P1 epic. Tag: Funnel. Small; precondition for the desktop app's attribution. Goal Close out the OpenRouter attribution funnel so Raxol appears on openrouter.ai/rankings and the desktop app can default to it. Design ROADMAP.md P1 "OpenRouter funnel" row + TODO.md (the one remaining #414 task): The :openrouter harness already sends app-attribution headers (HTTP-Referer, X-OpenRouter-Title, X-OpenRouter-Categories) via Backend.Selector / ExecutorConfig auth. Run the #414 live smoke with a real OpenRouter key (human-in-the-loop / key required). Confirm the openrouter.ai/apps?url=https://raxol.io listing appears. Bump raxol.io site copy to v2.6 / 14 packages (the #417 site work already merged as #418). Acceptance criteria :openrouter live smoke passes with a real key (captured as a :live_*-gated test / evidence) the openrouter.ai/apps listing for raxol.io is confirmed live site copy reflects v2.6 / 14 packages Effort: S. Priority: P1. References: Backen
Part of the Hermes Fast-Follow P1 epic. Tag: CATCH-UP. Pairs with the install-funnel PowerShell path. Goal Make native Windows first-class: tune the pure-Elixir driver, add Windows CI, and take the PowerShell installer path out of "preview". Design ROADMAP.md P1 "Windows first-class" row: Tune packages/raxol_terminal/lib/raxol/terminal/io_terminal.ex (the pure-Elixir driver used on Windows in place of the termbox2 NIF). Windows CI: drop the current Windows exclusions where the pure-Elixir path can actually run; keep NIF-only tests tagged. Finish the install.ps1 path from the install-funnel issue (Windows Burrito exe, pure-Elixir driver, %LOCALAPPDATA%\raxol, user PATH, no admin). Known noise to clear Windows undefined variable stdout noise from REPL.Evaluator.base_env/0 during Benchee runs (see TODO.md "Known noise"). Acceptance criteria the pure-Elixir driver renders the playground + a real app correctly on native Windows Windows CI runs the suite (pure-Elixir path) green; NIF-
Top Elixir Repositories with Beginner Issues (19)
Updated Daily via GitHub GraphQLConnect your people, tools and data with your custom AI agents. ZAQ is an open source collaborative and sovereign agentic operating system
vutuv is a social network. Think of it as a fast, secure and less annoying open-source alternative for LinkedIn, Facebook and X.
Official Elixir Language Server Protocol implementation
Middleware server for online gaming
The Main application that provides the core interface via the glific APIs
Write one app, render it to a terminal, a browser, or as agent tools. The terminal for your Gundam.
Lightning β‘οΈ is latest version of the OpenFn platform, a DPG and DPI building block that governments use to manage complex service/workflow automation and data integration projects.
π¬ Step-by-step tutorial creates a Chat App using Phoenix LiveView including Presence, Authentication and Style with Tailwind CSS
π¬ The Step-by-Step Beginners Tutorial for Building, Testing & Deploying a Chat app in Phoenix π
The PostgreSQL data layer for Ash Framework
:chart_with_upwards_trend: General purpose hits (page views) counter
Bonfire - tend to your digital life in community. Customise and host your own online space and control your experience at the most granular level.
Structured outputs, vectorization and tool calling for your Ash application
π¬ a curated list of quotes that inspire action + code that returns quotes by tag/author/etc. π‘
π₯ Phoenix is the web framework without compromise on speed, reliability or maintainability! Don't settle for less. π
:droplet: Learn the Elixir programming language to build functional, fast, scalable and maintainable web applications!
πͺ π UX-focussed Turnkey Authentication Solution for Web Apps/APIs (Documented, Tested & Maintained)
What if AI agents could form teams as fluidly as humans? Spawn specialists in milliseconds, share discoveries in real-time, review each other's work, and remember everything across sessions. Watch it all unfold in a live mission control UI. Open source.
Infinitely extensible mahjong web client.
How to make your first Elixir open-source pull request
Finding approachable Good First Issues in Elixir allows you to build real-world software engineering experience. Instead of submitting PRs to abandoned repositories, GetMerged verifies maintainer review speeds and first-timer acceptance rates before you write a single line of code.
Select any issue above to claim it directly on GitHub, or click a repository to inspect full maintainer review turnaround metrics and triage guidance!
Get this week's top welcoming repos + fresh Good First Issues for Elixir
Free weekly email, scoped to Elixir. No account needed - confirm once and unsubscribe anytime.