WPILib Won't Deploy: Every Cause and How to Fix It
Your WPILib deploy is failing? Work the decision tree: wrong folder in VS Code, team number, roboRIO image, JDK version, macOS network privacy. Fixes for each.
- to read
- 13 min
- words
- 3,203
- sections
- 12
to read
words
sections
A failed deploy is always one of three stages breaking, and the error text tells you which: your project (VS Code doesn't recognize the folder, or the code doesn't compile), the link to the robot (GradleRIO can't find a roboRIO to talk to), or the robot itself (found, but it rejects what you sent). Read the first red block in the terminal, not the last. Gradle dumps a stack trace at the bottom that is almost always noise; GradleRIO prints a plain-English headline near the top — Missing Target!, Dependency Error!, Compilation Error!, or Invalid RoboRIO Image Version! — and that headline is the actual diagnosis.
If you want the ten-second version: open the folder that directly contains build.gradle. Not the parent folder, not src, not a monorepo with three robot projects inside it. VS Code looks for .wpilib/wpilib_preferences.json at the root of the folder you opened, and if it isn't there, the WPILib commands quietly refuse to run. In my experience that single mistake produces more "the deploy button does nothing" reports than every network problem put together.
Everything below is checked against WPILib 2026 (2026.2.1, released 16 January 2026). Where a detail is season-dependent I say so, because these numbers move every year.
The decision tree
Run these four checks in order and stop at the first failure. Each eliminates a whole class of causes.
- Does VS Code show the WPILib commands? Press
Ctrl+Shift+P(Cmd+Shift+Pon macOS), typeWPILib, and look for "WPILib: Deploy Robot Code". If the list is empty or you get "Cannot deploy code since this is not a WPILib project", you have the wrong folder open. Stop here — nothing else matters yet. - Does
./gradlew buildsucceed? If the build fails, deploy never attempts to reach the robot — you have a compile error, a failing test, or a missing dependency. - Can you ping the roboRIO?
ping 172.22.11.2over USB, orping roboRIO-TEAM-FRC.localover Ethernet/Wi-Fi. If ping fails, this is a networking problem, not a code problem. - Does deploy reach the robot and then fail? If you see
Invalid RoboRIO Image Version!, or the deploy finishes but the Driver Station still says No Robot Code, the robot is talking to you and rejecting or crashing on what you sent.
Stage 1: the wrong folder is open in VS Code
The WPILib extension decides whether a workspace is a robot project by looking for .wpilib/wpilib_preferences.json directly inside the folder you opened. If it isn't there, isWPILibProject stays false and every WPILib command bails out with a message like "Cannot deploy code since this is not a WPILib project."
The extension does try to help. It searches exactly one level of subfolders for a .wpilib/wpilib_preferences.json, and if it finds one it pops a modal reading "Incorrect folder opened for WPILib project. The correct folder was found in a subfolder, Would you like to open it? Selecting no will cause many tasks to not work." Say yes. If you once clicked "No, Don't ask again for this folder", the prompt will never come back for that path and the failure becomes silent forever.
Two things defeat that helper: a project buried more than one level deep (Team1234-Code/2026/Reefscape/ won't be found from the repo root), and a repo holding several robot projects, where it asks you to pick and nothing works if you dismiss the prompt.
Fix: File → Open Folder, and pick the folder that contains build.gradle, settings.gradle, gradlew, and a hidden .wpilib directory side by side. That is the project root. Everything the toolchain does is relative to it.
One related trap: WPILib explicitly warns that creating projects on OneDrive is not supported, because OneDrive's caching interferes with the build system. Windows puts Documents and Desktop under OneDrive by default on many school laptops, so a project created in the obvious place is often sitting in a synced folder. Move it to something like C:\Users\<you>\FRC\.
Stage 2: the build fails before deploy ever starts
Deploy runs build first. If the build fails, you never touch the network — but the error can look unrelated, so check the headline.
Compilation Error! — GradleRIO's own note here is genuinely the right advice: "Check that all your files are saved, then scroll up in this log for more information." Auto-save on deploy is on by default (wpilib.autoSaveOnDeploy defaults to true), but if someone turned it off, you can absolutely deploy a stale build of unsaved code.
A failing unit test. wpilib.skipTests defaults to false, which means the check task runs on every deploy and a broken JUnit test blocks it. If a test is failing and you need code on the robot right now, run "WPILib: Change Skip Tests On Deploy Setting" — the extension then appends -x check to the deploy command. Fix the test afterwards; don't leave that setting on all season.
Dependency Error! — this one bites hardest at 11pm the night before a competition. GradleRIO prints: "Try again with ./gradlew build whilst connected to the internet (not the robot!)". The reason is a default most teams never notice: wpilib.deployOffline defaults to true, so the deploy command runs with --offline. Ordinary builds run online by default (wpilib.offline defaults to false), but deploy does not. So if you install a new vendor dependency and immediately hit deploy while tethered to the robot, Gradle has no cached artifact and no internet, and it fails. The fix is always the same: disconnect from the robot, get on real internet, run a full ./gradlew build, then reconnect and deploy.
Same root cause, slower fuse: online-installed vendor dependencies live in the Gradle cache, and WPILib warns you must rebuild with internet access roughly every 30 days or the cache clears and the library vanishes.
Could not apply requested plugin [id: 'edu.wpi.first.GradleRIO'...] — a corrupted Gradle cache. See the last FAQ below.
Team number: the three places it can be wrong
The team number is what turns into an address, so a wrong one looks exactly like a dead network.
In your project. .wpilib/wpilib_preferences.json holds four keys: currentLanguage, teamNumber, enableCppIntellisense, and projectYear. Read the number there, but change it with "WPILib: Set Team Number" rather than hand-editing. Deploying from VS Code passes the number as -PteamNumber=<n>, which wins over the JSON. From a bare terminal without that flag, GradleRIO falls back to the JSON, and a missing or negative value throws TeamNumberNotFoundException: "Could not find team number. Make sure either one is passed in, or the team number is set in the wpilib_preferences.json file."
On the roboRIO. The roboRIO's hostname and its 10.TE.AM.2 address both come from the team number burned into the controller, and imaging a roboRIO 2 from a microSD image does not set it. Set it with the roboRIO Imaging Tool (Edit Startup Settings), or — and this matters on macOS and Linux, where the NI Game Tools don't exist — with the cross-platform roboRIO Team Number Setter, reachable from "WPILib: Start Tool" in VS Code. Connect over USB, set the number, then press Reboot; it doesn't take effect until the controller restarts.
In the address you're typing. TE.AM notation splits a five-digit team number into octets: the first three digits, then the last two. Team 1234 is 10.12.34.2. Team 254 is 10.2.54.2. Team 33 is 10.0.33.2. Leading zeros are optional and the scheme covers team numbers up to 25599.
Stage 3: can your computer reach the roboRIO at all
When target discovery fails, GradleRIO prints Missing Target!, then a banner reading "Are you connected to the robot, and is it on?", then a line saying it could not find roborio. That means every address it knows was tried and none answered.
For the 2026 season, GradleRIO tries these, in this order:
roborio-TEAM-FRC.local(mDNS — the normal path)10.TE.AM.2(the radio's DHCP assignment)172.22.11.2(USB)roborio-TEAM-FRC,roborio-TEAM-FRC.lan,roborio-TEAM-FRC.frc-field.local(odd DNS environments)
It also asks the Driver Station: GradleRIO opens a socket to localhost:1742 and reads a JSON line the DS publishes with the robot's IP and whether it's on the field. That's why deploy sometimes works when mDNS is broken — if the DS has comms, GradleRIO borrows the address. It's also the mechanism behind "You can't deploy code while connected to the FMS! Ask the FTA to allow you to tether your robot."
To isolate the problem, use ./gradlew discoverRoborio, which prints the address of a connected roboRIO and nothing else. Then work the network layer:
- Plug in USB first. A USB Type-B cable gives you
172.22.11.2with no radio, no DHCP, and no mDNS involved. If that pings androboRIO-1234-FRC.localdoesn't, your problem is name resolution, not connectivity — either the roboRIO's team number is wrong, or a DNS server is intercepting.locallookups. On Windows the mDNS resolver comes from the NI Game Tools; macOS has it built in; Linux needs Avahi. - Disable every other network adapter — actually disable them in adapter settings, not airplane mode. A laptop on school Wi-Fi and the robot radio will route the deploy out the wrong interface.
- Check DHCP. The adapter must be on "Obtain an IP address automatically"; a static IP left over from a previous event is a classic.
- Turn off VPNs and proxies. WPILib names proxies explicitly as a cause of roboRIO networking failures.
- Windows Firewall. If ping works but deploy times out, suspect the firewall.
If ping fails even over USB, install the FRC Game Tools — they carry the roboRIO USB drivers. If you're on macOS or Linux, note that the Game Tools and the Driver Station are Windows-only, so you can write code and deploy from a Mac but you cannot run the Driver Station or the roboRIO Imaging Tool there. Our Driver Station connection guide walks the physical layer in more detail.
macOS: Local Network Privacy and multiple VS Code installs
This is a documented WPILib known issue, and the symptom is maddening: a deploy that hangs and reports Missing Target! on a Mac that pings the robot fine from Terminal.
macOS gates each app's access to local-network addresses, and the WPILib installer deliberately installs its own separate copy of VS Code instead of using an existing one. With both regular VS Code and WPILib VS Code installed, macOS can grant the permission to the wrong binary. Fix it at System Settings → Privacy & Security → Local Network and enable every VS Code entry.
If that doesn't clear it, WPILib documents a blunter workaround — run these in Terminal and then reboot:
sudo defaults write com.apple.network.local-network AllowedEthernetLocalNetworkAddresses -array "10.0.0.0/8"
sudo defaults write com.apple.network.local-network AllowedWiFiLocalNetworkAddresses -array "10.0.0.0/8"
That opens the whole 10.x.x.x range to every program on the machine. If you only connect to your own robot, narrow it to 10.TE.AM.0/24, and run only the Ethernet or Wi-Fi line if that's your only path.
The JDK and the bundled toolchain
WPILib deliberately does not use whatever Java you have installed. The 2026 offline installer ships Eclipse Temurin JDK 17.0.16+8, a pinned Gradle 8.11, the C++ cross-compiler toolchain, and its own VS Code build (1.105.1 in 2026.2.1), into C:\Users\Public\wpilib\2026 on Windows or ~/wpilib/2026 elsewhere — side by side with previous years, without touching your JAVA_HOME. The 2026 project template compiles at Java 17, and the JRE GradleRIO installs onto the roboRIO is Java 17 as well. If your setup isn't in place yet, start with our WPILib installation guide or the toolchain install walkthrough.
Version mismatches show up in three recognizable ways:
"Unsupported class file major version NN" from ./gradlew in a terminal. Gradle 8.11 runs on JDK 17 through 23; JDK 24 and newer are not supported by it. If JAVA_HOME points at a modern JDK — 24 is major version 68, 25 is 69 — Gradle dies before compiling a single file. Inside WPILib VS Code this never happens, because the extension points Gradle at the bundled JDK. From a plain terminal, either launch through WPILib VS Code or pass -D org.gradle.java.home pointing at the WPILib JDK.
edu.wpi.first.util.MsvcRuntimeException: Invalid MSVC Runtime Detected on Windows. This hits simulation rather than roboRIO deploys, and means a non-WPILib JDK supplied an old MSVC runtime. The message names the offending JVM path. Use the WPILib JDK.
Editor errors that don't match the build. If VS Code's Java language server is on a different JDK than Gradle, you get red squiggles with a clean build, or the reverse. "WPILib: Set VS Code Java Home to FRC Home" resyncs them.
roboRIO image vs. WPILib season
Before copying anything, GradleRIO SSHes in, reads the IMAGEVERSION line from /etc/natinst/share/scs_imagemetadata.ini, and compares it against a hardcoded list. A mismatch gives you:
Invalid RoboRIO Image Version!
RoboRIO image and GradleRIO versions are incompatible:
Current image version: 2025_v3.2
GradleRIO-compatible image versions: 2026_v1.2, 2026_v2.*
GradleRIO 2026.2.1 accepts 2026_v1.2 and any 2026_v2.x image. That list is specific to that release — a different WPILib update within the same season can widen it, and next season's list will be entirely different, so always trust the versions printed in your own error over any list you read online.
Two directions this breaks:
- Old image, new WPILib. You updated your laptop but the roboRIO still has last year's image. Reimage it. The image is separate from the firmware and must be updated yearly; firmware only needs touching on a brand-new controller, and only below v5.0. A roboRIO 1 is reformatted with the Imaging Tool over USB. A roboRIO 2 boots from a microSD card you write yourself with balenaEtcher or Raspberry Pi Imager from an
FRC_roboRIO2_YEAR_VERSION.img.zip(the SD button in the Imaging Tool shows you where they live) — imaging a roboRIO 2 directly with the Imaging Tool is not supported. - New image, old project. Use "WPILib: Import a WPILib 2020-2025 Gradle Project". In-place upgrades are not supported — the wizard copies your source into a fresh project and regenerates the Gradle files, so you must reinstall vendor dependencies and reapply any custom
build.gradleedits.
You can check the image yourself without deploying at all: ssh admin@172.22.11.2 (blank password — press Enter) then cat /etc/natinst/share/scs_imagemetadata.ini. Never change those SSH passwords; blanking them is what lets the deploy work at all.
Deploy succeeded but the Driver Station says No Robot Code
At this point the network is fine and the file transfer worked. Something on the robot is refusing to run it.
Read the RioLog. It opens automatically after deploy (wpilib.autoStartRioLog defaults to true) and it is where the stack trace lives. If your robot class throws in its constructor or robotInit(), WPILib prints "Unhandled exception instantiating robot..." then "The robot program quit unexpectedly. This is usually due to a code error." That's a code bug, not a deploy bug — a null vendor object, a duplicate CAN ID, a missing file under src/main/deploy.
Check the User button. Holding the roboRIO's User button for five seconds sets the NoApp flag, which stops robot code from starting. GradleRIO detects this and prints "NoApp is set on the device. Robot program cannot be started. Disable NoApp either with the imaging tool or by holding the User button for 5 seconds." A student pressing that button while probing for the reset button is more common than you'd think.
Reboot the roboRIO. WPILib lists a rare roboRIO 2.0 issue where a program deploys successfully but never starts; a reboot clears it. (If the User button caused the stop, a reboot alone will not bring the code back.)
Make sure you are actually running the new code. After a deploy, /home/lvuser/robotCommand holds the start command GradleRIO wrote and your jar sits in /home/lvuser. If you suspect you're running old code, ssh lvuser@172.22.11.2 and check the timestamps.
Our fuller writeup on that specific symptom is at No Robot Code on the Driver Station.
The 90-second verification checklist
Run this top to bottom before asking anyone for help. It's fast, and it produces a problem description someone can actually act on.
- VS Code title bar shows the folder that contains
build.gradle. Ctrl+Shift+P→WPILiblists "Deploy Robot Code"..wpilib/wpilib_preferences.jsonshows the rightteamNumberand this season'sprojectYear.- USB cable in,
ping 172.22.11.2replies. ping roboRIO-TEAM-FRC.localreplies (leading zeros omitted)../gradlew discoverRoborioprints an address../gradlew buildsucceeds while connected to the internet../gradlew deploy -PteamNumber=TEAM— and if it fails, note the first GradleRIO headline, not the Gradle stack trace.
One note about 2027
If you're reading this during the 2027 season, re-verify everything above. WPILib announced in April 2026 that a new Driver Station application is planned for the 2027 FRC season and that it supports Systemcore only, with the roboRIO staying on the existing Driver Station; Systemcore has been in FRC alpha testing since June 2025. Deploy targets, image checks, and address schemes are exactly what changes with new control-system hardware, so check docs.wpilib.org before trusting any season-specific number here.
Frequently asked questions
Why does my code deploy over USB but not over Wi-Fi?**
USB is a fixed 172.22.11.2 link with no radio, no DHCP, and no mDNS in the path, so it survives almost anything. Wi-Fi adds the radio's DHCP server (which hands the roboRIO 10.TE.AM.2) and mDNS name resolution. If USB works and Wi-Fi doesn't, first confirm the roboRIO's team number is set — a controller that doesn't know its team number can't be given the right address — then disable every other adapter on your laptop and confirm the one facing the radio is on automatic DHCP.
Can I deploy code while my robot is on the field?
No. GradleRIO reads the Driver Station's status over localhost:1742 and refuses with "You can't deploy code while connected to the FMS! Ask the FTA to allow you to tether your robot." That's deliberate. Deploy freely in the pits; on the field, ask the FTA if you genuinely need to.
Deploy says "Build Successful" but the Driver Station still shows No Robot Code. What now?
Look at the RioLog, not the Driver Station. "Build Successful" only means the files transferred and the start command ran. If your robot class throws during construction you'll see "Unhandled exception instantiating robot" plus a stack trace. If the console is completely empty, check whether someone held the User button for five seconds (that sets the NoApp flag and blocks startup), then reboot the roboRIO.
How do I deploy from a terminal without VS Code?
From the project root: ./gradlew deploy -PteamNumber=1234 on macOS/Linux, gradlew deploy -PteamNumber=1234 on Windows. That's essentially what the extension runs — it appends --offline by default and -x check if you've enabled skip-tests. Make sure the Gradle wrapper is using the WPILib JDK; from a plain shell it picks up your system JAVA_HOME, and Gradle 8.11 won't run on JDK 24 or newer.
**Is it safe to delete the .gradle folder?
Yes, and it's WPILib's documented fix for the corrupted-cache error where Gradle claims it can't find the GradleRIO plugin. Delete ~/.gradle (C:\Users\<you>\.gradle), then run a full build while connected to the internet — the first rebuild has to re-download everything, so don't do this in the pits an hour before a match.
Go deeper
Bookmark the fix before you need it again
Pit problems repeat. A free account lets you bookmark troubleshooting guides and checklists so they're one tap away at competition.
Create a free accountKeep reading
More from the pit
Start learning FRC — free
Structured lessons and quizzes across every department. Create a free account to save your progress, track your team, and earn a certificate.