Good First Issues in Rust
Explore curated starter issues in high-scoring Rust 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 Rust 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)
Hi, I'm pretty new to rust - so I'm not completely sure if this is a bug or a feature request (and there is still the possibility that I'm doing something wrong). rust-analyzer 1.98.0 (88d9e12a 2026-08-18) I want to extract a struct into its own module using "Extract module", but when the struct is already imported via a use binding, the assist adds a redundant qualifier to usages of that struct instead of updating the existing import. There are two files, main.rs and my_module.rs // main.rs use crate::my_module::{First, Second}; mod my_module; fn main() { let first = First {}; let second = Second {}; } // my_module.rs pub(crate) struct First {} pub(crate) struct Second {} Running "Extract module" on struct First results in the following code: // main.rs use crate::my_module::{Second, modname::First}; // <- already imported mod my_module; fn main() { let first = modname::First {}; // <- qualifier added let second = Second {}; } and // my_module.rs mod modname { pub(
Bug description Bug description iggy-server panics immediately at startup on Intel macOS (x86_64) and never binds a listener. The build succeeds; the failure is at runtime. The guard in core/server_common/src/executor.rs:87 applies thread_pool_limit(0)` on every target except macOS aarch64 #[cfg(not(all(target_os = "macos", target_arch = "aarch64")))] proactor.thread_pool_limit(0); On macOS x86_64 the condition is therefore true and the zero limit is applied. compio's polling driver (used on macOS, since there is no io_uring) routes fs operations through the blocking pool, so the first fs operation panics. The comment directly above that line describes the exclusion as applying to macOS generally, with no architecture qualifier Expected: server starts on Intel macOS. Actual: panics before binding any listener. Why CI did not catch it The only macOS Rust job is build-macos-aarch64 on macos-14 (.github/workflows/_test.yml:44). macos-15-intel appears only in _build_python_wheels.yml. Inte
Part of #496. Build a small CLI that converts the output of h5i browser audit --json into a self-contained HTML report. h5i already provides the structured audit data. This tool should make that record easy to archive, attach to a CI run, or send to someone who does not have h5i installed. It is not intended to replace the live h5i ui. Estimated effort: 2 to 4 hours. What to build The basic workflow should be: h5i browser audit --json > audit.json h5i-audit-report audit.json --out report.html Piping the audit directly should also be supported if convenient: h5i browser audit --json | h5i-audit-report > report.html The report should include: Session identity, starting URL, placement, and ending reason. The policy digest and available evidence information. One ordered timeline containing browser actions, requests, handovers, and lifecycle events. Clear visual distinction between allowed and denied requests. The reason recorded for each denied request. Filters for event type and request
pub type State { Open HalfOpen Closed } pub fn main() { let state = Open case state { Closed, HalfOpen -> "do something" // ^ expecting hint about using | // got "Incorrect number of patterns Expected 1 pattern, got 2. This case expression has 1 subject, but this pattern matches 2. Each clause must have a pattern for every subject value. " Open -> "another do something" } }
scripts/setup-dev.sh installs protoc and nothing else. But anyone who runs cargo lint-all, cargo test -p wingfoil --all-features, or touches the Aeron adapter also needs clang, libclang-dev, uuid-dev, libbsd-dev and CMake ≥ 3.30. Those instructions currently exist only as a copy-paste block in CLAUDE.md ("Aeron adapter system dependencies"), which means a contributor typically discovers them the expensive way: a long, apparently successful build that ends at link time with rust-lld: error: unable to find library -lbsd libbsd-dev is the one that is easy to miss, because nothing fails until then and only on an --all-features target. CMake fails differently and just as late — the vendored rusteron-media-driver Aeron sources set a 3.30 floor in their own cmake_minimum_required, so the 3.28 that ships on many distros aborts the build script with CMake 3.30 or higher is required. Where to start Teach setup-dev.sh a second mode — a flag or a positional argument, e.g. scripts/setup-dev.
StreamOps::timed (crates/wingfoil/src/fluent.rs, next to print) passes each value through unchanged and prints a performance summary at the end of the run. It is not exposed in Python — grep -rn '\btimed\b' crates/wingfoil-python/src finds only unrelated hits. Its neighbour print is bound, and the two are the same shape, so this is a small, well-modelled first contribution to the Python crate. Where to start PyStream::print in crates/wingfoil-python/src/graph.rs (~line 662) is the model. The binding is one line over the erased PyElement edge plus rustdoc: pub fn timed(&self) -> PyStream { self.wrap(self.stream.timed()) } Check the bound before assuming it compiles: timed wants T: Clone + Default + 'static and PyElement satisfies that (print additionally needs Debug and gets it). If it does not compile, say so on the issue rather than working around it — that would be a real finding about the erased edge. The recipe for the Python step is /new-op §7 (.claude/commands/new-op.md)
Third and last of the doctest issues (see the value-transform and rate/window ones). crates/wingfoil/src/fluent.rs documents ~90 public methods and only 7 carry a runnable example. The multi-input combinators are the ones where prose alone genuinely cannot settle the question — which input ticks the output, what the passive variant holds, who wins a same-instant tie. Every one of those is a two-line assert. Scope On StreamOps, in crates/wingfoil/src/fluent.rs: join, join3, try_join, try_join3 join_passive, try_join_passive merge, merge_all sample, filter Partial PRs are welcome — one method is a valid PR. Where to start Copy the filter_map example in the doc block immediately above fn filter_map in fluent.rs. What each family should actually demonstrate: join vs join_passive — the whole point is the difference. join ticks when either input ticks; join_passive ticks only with the active one and reads the other's held value. One example each, wired over the same two streams, mak
Companion to the value-transform doctest issue. crates/wingfoil/src/fluent.rs documents ~90 public methods and only 7 carry a runnable example, so most of the combinator reference on docs.rs is a sentence and a signature. These particular combinators are the ones most often misread from a one-line description — leading vs. trailing edge, whether the value is dropped or held, whether the node ticks or stays silent — so an example is worth more here than anywhere else. Scope On StreamOps, in crates/wingfoil/src/fluent.rs: audit, window, buffer limit, skip, step_by skip_while, take_while delay throttle is deliberately not on this list — its contract wording is #929, and the example belongs in that PR alongside the prose. Partial PRs are welcome — one method is a valid PR. Where to start Copy the filter_map example in the doc block immediately above fn filter_map in fluent.rs; it is the house shape. Two of these need more care than a copy: delay is the one that demonstrates Tick
crates/wingfoil/src/fluent.rs documents ~90 public methods and only 7 of them carry a runnable example — grep -c '/// ```' crates/wingfoil/src/fluent.rs returns 14 fence lines. docs.rs is where a new user lands first, and for almost every combinator it currently shows a one-line sentence and a signature. This is the cheapest possible improvement to the front door, and it is already gated: cargo test --doc -p wingfoil --all-features runs every fence, so a wrong example fails CI rather than rotting. Scope The value-transform group on StreamOps, in crates/wingfoil/src/fluent.rs: map, try_map, map_filter with_time, ticked_at, ticked_at_elapsed difference, pairwise, enumerate Sibling issues cover the rate/window group and the join/merge group. Partial PRs are welcome — one method is a valid PR. Where to start Copy the existing filter_map example, in the doc block immediately above fn filter_map in fluent.rs. It is the house shape and it is 14 lines: build a graph, drive it from ticker
Asyar Version v0.1.1-45 Platform / OS Linux Description On Linux, background services (like clipboard history tracking active source apps) log the following platform error: Platform error: Failed to retrieve frontmost application metadata { "platform": "Failed to retrieve frontmost application metadata" } Steps to Reproduce Logs or Additional Context
dial9/perf-self-profile/src/memory_profiling/hook.rs Lines 308 to 319 in 01e1ab3 if let Entry::Occupied(o) = liveset.entry(addr) { let (size, alloc_ts_ns) = *o.get(); o.remove_entry(); let sample = RawFree { tid: current_tid(), addr, ts_ns: clock_monotonic_ns(), size, alloc_ts_ns, shutdown: false, }; inner.rings.push_free(sample); This ends up attempting to reserve an e
agentgateway should document how to export telemetry to each observability platform below. For every platform, add integration guides for both standalone and Kubernetes deployments. Each guide should cover prerequisites, configuration, and verification, and should be linked from the documentation navigation. A checkbox is complete when both deployment guides are merged. Arize AX Axiom Braintrust Coralogix Dash0 ClickStack CoreWeave Dynatrace Elastic Honeycomb HoneyHive Langfuse LangWatch Laminar LangSmith Last9 Lunary Middleware New Relic OpenLIT PromptLayer Pydantic Logfire SigNoz Splunk Traceloop
Split out of #803, which had to say this before it could explain what debounce is for. It stands on its own, it is unblocked, and it is docs-only. The gap throttle is leading-edge only: it emits the first value of a burst and suppresses the rest — including the last one. Neither doc site says so. The op rustdoc (Throttle, crates/wingfoil/src/ops.rs — search pub struct Throttle) says "emits the first value, then suppresses until at least interval has passed since the last emit". That is the mechanism, stated accurately, but the reader has to derive the consequence themselves. The fluent method (StreamOps::throttle, crates/wingfoil/src/fluent.rs) says only "Rate-limit: emit at most once per interval." That is actively misleading about which value you get — and the fluent doc is the one most readers actually see, because it is what shows up at the call site. Why it matters: for "the user stopped typing", "the burst settled", "emit the final state after the storm", you want the tra
Split out of #803, which carried "end of run with a value still pending — emit it or drop it?" as an open decision. The convention already exists in the catalog; it is just not written down anywhere a new op author would find it. Writing it down settles that decision for #803 and for every scheduling op after it. What exists today Two ops flush pending state on the final cycle, both in crates/wingfoil/src/ops.rs: Window — if out.is_none() && ctx.is_last_cycle() && !state.buffer.is_empty() Buffer — if state.len() >= *cfg || (!state.is_empty() && ctx.is_last_cycle()) So the convention is flush: an op holding a value the user would otherwise never see emits it on the last cycle rather than dropping it. Ctx::is_last_cycle() (crates/wingfoil/src/op.rs) is how you ask. The caveat that needs writing down with it is_last_cycle is not propagated into islands — Ctx::nested hard-codes is_last_cycle: false. A boundary-flush op inside a nested() composite therefore flushes only on its own
context apache/arrow-rs#3199 apache/arrow-rs#10902 once apache/arrow-rs#10902 (arrow-rs v60.0.0) is merged update call sites in DataFusion to use the new equal_datatypes instead of custom logic. know callsites #4347 #4233
Search for duplicate feature request I already searched, and this feature request or improvement is not a duplicate. Feature scope Completely new feature Feature request related to a problem For development purposes, you often want to frequently open your web browser to check if your website is working properly. Describe the solution you'd like Add a config option for automatically opening the web browser when running the tool. Many web dev tools often provide a similar option because it helps reduce the friction during development. Describe alternatives you've considered Open the web browser manually, but that can get tedious. Build target All targets Additional context There's a convenient Rust library made just for this purpose: https://github.com/amodm/webbrowser-rs A similar Rust tool called simple-http-server also provides a similar option in the form of an --open flag. But that tool isn't as configurable as static-web-server.
in vanilla, blocks dont break in creative while youre holding a sword. on Steel they break from one click. this affects every sword. I tested wooden and diamond myself, and a Fabric client gametest reproduced it with a wooden sword on commit b3cdff21f. how to reproduce: join a creative world hold any sword click a stone block once ItemStack::can_destroy_blocks_in_creative() already exists, but the block breaking code doesnt check it before removing the block.
found this while looking through #411, but the bug was already there before that PR. tick_active_item_use only checks if the hand still has the same item type. it then runs on_use_tick with its local stack and writes that stack back into the hand no matter what happened during the callback. if on_use_tick changes the held stack, Steel can finish using the old stack and overwrite the new one. vanilla uses the held stack while ticking and checks the full stack again before finishUsingItem. we should match that without bringing back the empty hand bug that #411 fixes. a test where on_use_tick replaces the held stack should cover it.
Description Gemma 4 31B consistently segfaults using the current Dynamo main vLLM runtime. vLLM version: 0.27.1 Reproduction Run inside the Dynamo container, replacing MODEL_PATH with the Gemma snapshot path: VLLM_USE_V2_MODEL_RUNNER=1 python3 -m dynamo.vllm \ --model "$MODEL_PATH" \ --served-model-name google/gemma-4-31B-it \ --discovery-backend file \ --trust-remote-code \ --tensor-parallel-size 4 \ --max-model-len 8192 \ --max-num-batched-tokens 8192 \ --max-num-seqs 128 \ --gpu-memory-utilization 0.9 \ --enable-prefix-caching \ --enable-chunked-prefill \ --reasoning-parser gemma4 \ --dyn-tool-call-parser gemma4 \ --dyn-reasoning-parser gemma4 \ --custom-jinja-template /workspace/examples/chat_templates/gemma4_tool.jinja \ --model-loader-extra-config '{"enable_multithread_load":true,"num_threads":128}' \ --no-enable-log-requests \ --enforce-eager \ --kernel-config '{"enable_flashinfer_autotune":false,"enable_cutedsl_warmup":false,"enable_jit_war
Description sdk-python declares tasks: ["lint", "test", "build"], and each task becomes its own job on its own runner. The build task compiles the wheel and throws it away: its dist/ never reaches Upload test artifacts, which only runs under test. So the crate is compiled twice per push and nothing is shared between the jobs. At the same time apache_iggy.pyi has no freshness gate. The file header says it is generated by pyo3_stub_gen, the README says "nothing in CI checks stub freshness", and the stub has already drifted from the source: describe_options sits in a different position with its return type written as builtins.list[OptionSpec], and two docstrings were edited by hand. Checking this needs a built crate, so today there is nowhere cheap to put the check. Affected area / component CI / build / tooling Proposed solution Drop the build task and move maturin build -o dist into test: tasks: ["lint", "test"] lint = ruff + cargo fmt + clippy + pyrefly, unchanged test = wheel + stub
Should probably have a list endpoint that allows iterating through a store. We could provide support for predicate conditions as well which effectively gives us an operation like message ListStore { string store = 1; optional uint64 start_key = 2; // StoreKeyId perhaps as a token to start from uint32 limit = 3; // Max number of items to return optional PredicateCondition condition = 4; // Filter results by predicate optional string schema = 5; // Schema/namespace } Given that ordering has no semantic meaning, should we bother to implement ordering. If yes we could still sort by StoreKeyId first. Checklist follow up to this would be: Integrating endpoint into Ahnlich AI and CLI Updating libraries to include new endpoint Updating https://ahnlich.dev public docs VectorDBZ as #396 stated
Drawing inspiration from the GraalVM JDK directory structure, I suggest placing all executable files—such as smolvm and smolvm-bin—in a bin directory. Template and configuration files—such as storage-template.ext4.zst and overlay-template.ext4.zst—should be placed in a conf directory. The root directory should be reserved solely for informational files, such as README.txt and LICENSE.txt. This approach ensures a clear directory structure and facilitates easier management. smolvm-1.13.0-darwin-arm64 directory layout: 0755 drwxr-xr-x@ - . 0755 drwxr-xr-x@ - ├── agent-rootfs 0755 drwxr-xr-x@ - │ ├── bin 0755 drwxr-xr-x@ - │ ├── dev 0755 drwxr-xr-x@ - │ ├── etc 0755 drwxr-xr-x@ - │ ├── home 0755 drwxr-xr-x@ - │ ├── lib 0755 drwxr-xr-x@ - │ ├── media 0755 drwxr-xr-x@ - │ ├── mnt 0755 drwxr-xr-x@ - │ ├── opt 0555 dr-xr-xr-x@ - │ ├── proc 0755 drw
The viz smart command with the --dict-info and --dictionary options has the ability to produce localized Data Schematics when --language is set. The localizations were drafted by Fable 5 and require validation by native speakers. See https://github.com/dathere/qsv/blob/master/src/cmd/viz_i18n.rs and https://github.com/dathere/qsv/tree/master/src/cmd/locales
stop_all_sessions() and get_current_session_name() read session names through tmux_command(), which does not force UTF-8. When aoe's own environment has no UTF-8 in LC_ALL / LC_CTYPE / LANG and TMUX is unset (a systemd unit with a scrubbed environment, or a minimal container), tmux sanitizes each wide character to one _ per display column. Same mechanism as #3536, just a different call site. stop_all_sessions() (src/tmux/mod.rs:872) is the one that hurts. SESSION_PREFIX is aoe_, pure ASCII, so a mangled name still passes is_aoe_session: if is_aoe_session(line) { if let Some(pid) = crate::process::get_pane_pid(line) { crate::process::kill_process_tree(pid); } let _ = tmux_command().args(["kill-session", "-t", line]).output(); killed += 1; } So with a mangled name: get_pane_pid(line) returns None, and the agent process tree is never killed kill-session -t <mangled> fails into the let _ = killed += 1 runs anyway The panic button reports "stopped N" while every ag
GNU sed supports case-conversion escapes in the replacement text of s///. None of them work in uutils sed today. $ echo "abc def" | sed 's/b\(.*\)/\U&/' script uutils sed GNU sed 4.9 s/b\(.*\)/\U&/ aUbc def aBC DEF s/b\(.*\)/\u&/ aubc def aBc def s/b\(.*\)/\L&/ a\Lbc def abc def s/b\(.*\)/\l&/ a\lbc def abc def s/b\(.*\)/\E&/ a\Ebc def abc def
Not everyone has Rust installed on their system and can do cargo install. So to make adoption easier, people should be able to install a binary easily. Should work on: Windows Linux MacOS Can probably get inspiration from probe-rs: https://github.com/probe-rs/probe-rs/blob/b251a5c79ced3225fb7a7f8e08ee917055474aa9/.github/workflows/release_crates.yml That ultimately uses: https://github.com/axodotdev/cargo-dist
Describe the bug When a query renames a column using a DataFusion reserved name, it currently fails with an error message that does not clearly tell the user how to resolve the issue. For example: Arrow error: Invalid argument error: Invalid comparison operation: Float64 > Boolean Even though the user's query doesn't contain a Float64 > Boolean comparison, the error message is misleading. It would be good to improve the error message so that it clearly tells the user to choose a different column name instead of using a DF reserved name. To Reproduce ❯ datafusion-cli DataFusion CLI v55.0.0 > CREATE TABLE readings(range_idx INT) AS VALUES (1); 0 row(s) fetched. Elapsed 0.039 seconds. -- ❌ bug reproducer, `__common_expr_2` is a DF reserved column name > SELECT CASE WHEN (range_idx = 1) THEN normalized_value ELSE 0.0 END AS result FROM ( SELECT range_idx, CASE WHEN (range_idx = 1) THEN capped_value ELSE 0.0 END AS normalized_value FROM ( SELECT range_idx,
Summary ADDR=$$(forest-wallet --remote-wallet import $KEY) forest-wallet --remote-wallet set-default "$$ADDR" ⬇️ ADDR=$$(forest-wallet --remote-wallet --set-default import $KEY) Kind of nicer ergonomics, but obviously not a huge deal. Completion Criteria Allow setting the address as default when importing a key Tests Additional Links & Resources
Observed on main @ 103b1d1 (debug build, single-node dev stack) during independent Stage-3 qualification reruns. Sequence: a fresh stack (--metadata-create), a handful of coordination writes (workspace create, three publishes), then SIGKILL of the serving owner ~1 second after the last write - i.e. inside the metadata flush window. Every subsequent reopen attempt (--metadata-reopen) fails permanently with: nokv: metadata store failed: metadata store is corrupt: node corrupt at FileBlobStore::Manifest::duplicate slot The corruption is durable: no retry ever succeeds and the store is lost. Killing the owner after a few seconds of quiescence never reproduces it (all prior Stage-2/Stage-3 SIGKILL drills passed with the kill issued post-quiescence); the mid-write timing is the trigger. Impact: crash-consistency - a kill -9 (or power loss) at the wrong moment costs the whole metadata store. The write-path claim that a crash between operations is recoverable does not currently extend to a cr
The ParadeDB index carries special-cased ltree support: SearchFieldType::Ltree with facet-encoded storage (schema/mod.rs, postgres/catalog.rs), pushdown of the descendant operator <@ to a native facet query (customscan/pushdown.rs), and facet-to-path decoding on the aggregate side. With bitmap intersection (#6088), a plain ltree GiST index covers these predicates with no special casing: ltree's operators are ordinary members of gist_ltree_ops' operator family, so the direct opfamily-match arm harvests them. Verified on a 100k-row table: both path <@ 'Top.Cat7' and the lquery match path ~ '*.Cat7.*{1}' plan a Bitmap Intersection over the GiST index with exact result parity against heap filtering. Proposal: deprecate the in-index ltree support and recommend a standard ltree GiST index alongside the ParadeDB index instead. Broader coverage: the pushdown handles only <@; the bitmap path covers <@, @>, ~, ?, @ — anything in the opclass. Less surface: removes the facet encoding, the type
Top Rust Repositories with Beginner Issues (20)
Updated Daily via GitHub GraphQLThe power of Raycast. The speed of Alfred. Privacy by design.
Local-first MCP gateway. One port for every tool and every AI client: lazy discovery (~90% token savings), tool integrity + quarantine, secrets in the OS keychain.
Scientific computing that fits on a microcontroller. Estimation, control, kinematics, Lie groups, calculus, autodiff and linear algebra in stable no_std Rust with no heap, no panics and no unsafe. Run the same code on your laptop and your Cortex-M0.
A luxurious package manager for Lua
Repo-native governance kernel for bounded, convergent, proof-backed agent work.
A native TypeScript/JavaScript compiler written in Rust. Compiles TypeScript/JavaScript directly to executables using SWC and LLVM.
WGSL embedded in Rust
Native Spotify client for the GNOME desktop.
The lightest AI sandbox. A process-based sandbox for Linux, no container, no VM, no privilege, no prompt injection
A Wayland Compositor
Embeddable spreadsheet engine - parse, evaluate & mutate Excel workbooks from Rust, Python, or the browser. Arrow-powered, 400+ functions.
Alternative R Frontend — a modern R console written in Rust
Sandboxed collaboration for multi-agent teams: a Git-backed message forum with each agent isolated in its own disposable sandbox. Turn a Git repository into a secure message forum for AI agents.
Unica (Ю́ника) — публичный плагин Codex и Claude Code для разработки на 1С:Предприятии.
Fast search engine on object storage, with full text search, vectors, and SQL, natively on Parquet.
BitFun combines a high-performance agent runtime written in Rust with a polished desktop application. It pairs the depth of a Code Agent with open, general-purpose capabilities for work beyond software development.
A software library of stochastic streaming algorithms, a.k.a. sketches.
graph based stream processing framework
A self-contained browser engine that fetches, renders, and extracts web content as Markdown, JSON, or screenshots — no Chromium, no API key, no setup.
modular service framework to move and transform network packets
How to make your first Rust open-source pull request
Finding approachable Good First Issues in Rust 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 Rust
Free weekly email, scoped to Rust. No account needed - confirm once and unsubscribe anytime.