Jump to content

Mods not loading via Steam on Linux Mint


nuagerebelle
  • Branch: Live Branch Version: Linux Pending

I'm using Steam on Linux Mint 22. When I install ONI, the mods don't download / install. Sometimes, a workshop item shows up in the download screen, but when I try to get it to download it fails automatically without an error. See attached video.


Steps to Reproduce
  1. Install Steam. (I tried from the Software Manager, and when that didn't work out for me, I uninstalled Steam and reinstalled it using the .deb on Steam's own website.)
  2. Install ONI (I have a bunch of workshop mods I already subscribe to. For good measure, I toggled one off and on.)
  3. Start the game and check the mod list from the game's main menu and see that it's empty. (bug)
  4. Look in `~/.config/unity3d/Klei/Oxygen Not Included/mods` and see the only thing there to be a single file called `mods.json` with the following contents: (bug)
{
"version": 1,
"mods": []
}

Other Info:

  • Sometimes, a workshop item shows up in the download screen, but when I try to get it to download it fails automatically without an error. See attached video.
  • I just downloaded Rimworld and I had a bunch of subscribed mods for that and the mods seem to have downloaded correctly, so this seems ONI-specific somehow.
  • Attaching the contents to lshw, in case that's useful.

Has anyone else run into this? If so, any tips as to how to fix this?

lshw.txt




User Feedback


Sounds like the issue is with the Steam client. You might be able to find some information in Steam's workshop_log.txt. On Windows it's located at C:\Program Files (x86)\Steam\logs\workshop_log.txt but I'm not sure where it would be on your system.

  • Like 1

Share this comment


Link to comment
Share on other sites

For future reference, I found workshop_log.txt here: ~/.local/share/Steam/logs

I'm attaching two instances of this log:

  • workshop_log.txt is what got written to the file when I opened steam and tried to subscribe to a new mod.
  • workshop_log.txt-tmp is what got written to the log before that. Near the end are the results of my attempts to manually install the mods via SteamCMD.

Another curious thing is the fact that within the Steam UI, the mods seem to have a size of 0B. Notice how this is not the case for Rimworld:

image.png.e8f4aea6650cb338be747854a62b7e73.png

 

image.png.2cc2c75c04e12112fbb2e963ab5865dd.png

workshop_log.txt-tmp workshop_log.txt

  • Thanks 1

Share this comment


Link to comment
Share on other sites

We're still using an older steam modding API so that may be the cause of the difference in behaviour between Oxygen Not Included and Rimworld. The error message "I/O Operation Failed" is not super descriptive. Do you know how to use strace and/or tcpdump? The former could show exactly what failure is happening (for example is it network or disc I/O, and what is the precise error?), the latter could show the network traffic to rule out or confirm certain network failures.

Since it works on other distributions I'd look into differences - firewalling especially. Are you running a firewall? If so, do the blocked packet counts go up when you're trying to download mods?

Since it's not an officially supported distribution we can't promise a resolution but I'm happy to support you in your investigation!

  • Like 1

Share this comment


Link to comment
Share on other sites

Appreciate your help with this.

I wasn't sure how to get the count of blocked packets, but I momentarily turned off my firewall to run "workshop_download_item 457140 1717463209" in SteamCmd and continued to get the same error "ERROR! Download item 1717463209 failed (I/O Operation Failed)." This makes me feel like the firewall is not the issue. Let me know if you disagree and want more testing around this.

I also tried running "sudo strace -p [steamcmd pid] 2>&1 | tee strace_output" while running the SteamCmd command. I attached the output. A lot of it is garbage, but if you search for "ERROR", you'll find the part of the output corresponding to my download attempt.

I can try capturing something similar with tcpdump, but I'm less familiar with it and wasn't sure if there was a specific filtering you wanted. I tried "sudo tcpdump --interface wlp3s0" and it felt very, very noisy.

strace_output

Share this comment


Link to comment
Share on other sites

For packet counts, if you're using iptables you can do iptables -L -nv and that should show the counts for each rule. You can use -Z to zero out those counters right before running your test to confirm. That said, if you turned it off and it still happened then that's a pretty strong indication that this is not the issue.

For the strace you may need to run it again adding -f.

       -f
       --follow-forks
                   Trace child processes as they are created by currently traced processes as a result of the fork(2), vfork(2) and clone(2) system calls.  Note that -p PID -f will attach all threads of process PID if it is multi-threaded, not only thread with thread_id = PID.

As you can see from the relevant lines

write(1, "Downloading item 1717463209 ...\n", 32) = 32
gettid()                                = 508322
write(1, "ERROR! Download item 1717463209 "..., 67) = 67

and even the preceeding context whatever interesting stuff is going on seems to be on a different thread to the main one you're tracing (though I'd expect to see more synchronization primitives like mutexes here, I wonder if that's part of the problem....)

Yeah, tcpdump is going to be VERY noisy. The basic idea would be to capture traffic from steam (which will PROBABLY be on port 443?) and look for things like aborted TCP connections or the like. But since you've been able to strace successfully I think that's the more productive path to investigate for now. Once we get all the threads we should be able to see what network traffic it's initiating and so even if we decide to look into things with tcpdump we'll have a narrower filter to apply.

Thanks for looking into this, I believe there's at least one other user with your issue so I appreciate you taking the time to help debug it for them and for anyone else who runs into this down the road!

  • Like 1

Share this comment


Link to comment
Share on other sites

[pid 39422] openat(AT_FDCWD, "/home/arg/.local/share/Steam/steamapps/workshop/appworkshop_457140.acf.async39415.tmp", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0777) = 5
[pid 39422] write(5, "\"AppWorkshop\"\n{\n\t\"appid\"\t\t\"45714"..., 4411) = 4411
[pid 39422] fdatasync(5)                = 0
[pid 39422] close(5)                    = 0

Here Steam in one of its worker threads is writing 4411 bytes into appworkshop_457140.acf.async39415.tmp and making sure those bytes actually made it to disc.


[pid 39422] access("/home/arg/.local/share/Steam/steamapps/workshop/appworkshop_457140.acf", F_OK) = 0
[pid 39422] access("/home/arg/.local/share/Steam/steamapps/workshop/appworkshop_457140.acf.async39415.tmp", F_OK) = 0
[pid 39422] rename("/home/arg/.local/share/Steam/steamapps/workshop/appworkshop_457140.acf.async39415.tmp", "/home/arg/.local/share/Steam/steamapps/workshop/appworkshop_457140.acf") = 0

Now steam in that same thread atomically renames the temp file over the original (if any). This is a really standard and good way of writing files.


[pid 39422] futex(0xf586d6e4, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY <unfinished ...>

Now that thread is waiting on a lock of some kind....


[pid 39415] <... clock_nanosleep resumed>0xff88bd8c) = 0
[pid 39415] waitid(P_ALL, 0, 0xff88bce0, WNOHANG|WEXITED|WNOWAIT, NULL) = -1 ECHILD (No child processes)

Now the main thread does a non-blocking check if any of its children have died. They haven't.


[pid 39415] write(13, "\1\0\0\0\0\0\0\0", 8) = 8

Now it writes something to file descriptor 13. That was opened before you started the strace so I don't know what it is. If you want to check you can look at the output of ls -l /proc/<pidofsteam>/fd/13. But judging by what happens later I'm guessing it's being used to communicate between threads?


[pid 39419] <... epoll_wait resumed>[{events=EPOLLIN, data={u32=1704603936, u64=17567875771016032544}}], 1, 41) = 1

Some other thread now reports that one of the file descriptors it had been waiting for has data to be read. Spoiler alert, it's the bytes that were written on the line above.


[pid 39415] futex(0x659966b0, FUTEX_WAIT_BITSET_PRIVATE, 0, {tv_sec=12158, tv_nsec=518649318}, FUTEX_BITSET_MATCH_ANY <unfinished ...>

Main thread waits on a lock.

[pid 39419] read(12, 0xf2955c78, 8)     = -1 EAGAIN (Resource temporarily unavailable)
[pid 39419] read(13, "\1\0\0\0\0\0\0\0", 8) = 8

Ohh look, it's those same 8 bytes that were written above.


[pid 39419] gettid()                    = 39419
[pid 39419] futex(0x659966b0, FUTEX_WAKE_PRIVATE, 2147483647) = 1
[pid 39415] <... futex resumed>)        = 0

39419 now wakes up 39415...


[pid 39419] poll([{fd=13, events=POLLIN}], 1, 0 <unfinished ...>

...and goes back to waiting for any of its file descriptors to have news.


[pid 39415] futex(0x6599666c, FUTEX_WAKE_PRIVATE, 1 <unfinished ...>
[pid 39419] <... poll resumed>)         = 0 (Timeout)
[pid 39415] <... futex resumed>)        = 0
[pid 39419] epoll_wait(7,  <unfinished ...>
[pid 39415] gettid()                    = 39415
[pid 39415] gettid()                    = 39415
[pid 39415] gettid()                    = 39415
[pid 39415] gettid()                    = 39415
[pid 39415] gettid()                    = 39415
[pid 39415] gettid()                    = 39415
[pid 39415] gettid()                    = 39415
[pid 39415] gettid()                    = 39415
[pid 39415] gettid()                    = 39415
[pid 39415] gettid()                    = 39415
[pid 39415] gettid()                    = 39415
[pid 39415] gettid()                    = 39415
[pid 39415] gettid()                    = 39415
[pid 39415] clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=0, tv_nsec=25000000},  <unfinished ...>
[pid 39429] <... clock_nanosleep resumed>0xf1cfdc5c) = 0
[pid 39429] clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=0, tv_nsec=25000000},  <unfinished ...>
[pid 39415] <... clock_nanosleep resumed>0xff88bd8c) = 0
[pid 39415] write(1, "Downloading item 1717463209 ...\n", 32) = 32
[pid 39415] gettid()                    = 39415
[pid 39415] write(1, "ERROR! Download item 1717463209 "..., 67) = 67

Main thread writes downloading and then writes failed without doing any syscalls whatsoever in between. That's kinda weird to me. Most importantly there's no real evidence of why it failed in any of this.... Even weirder, when we look over all the failed syscalls in your trace we don't really see anything that would explain the problem.

grep '= -1' ~/Downloads/strace_output\(1\)  | grep -v ECHILD | grep -v EAGAIN

get rid of ECHILD (none of your kids are dead yet), EAGAIN (you asked for non-blocking I/O and there's no I/O available). We're left with:

ETIMEDOUT Maaaaaybe but there are an awful lot of those locks timing out

ENOENT Again, maaaaybe but it seems to be mostly steam checking that temp files don't exist before attempting to write to them, @EricKleimaybe you can take a peek over these paths though and see if any of them ring a bell for you?

EACCES This one's normally gold but in this case it's just steam trying and failing to access tracing mechanisms like /sys/kernel/debug/tracing/trace_marker. Why would that have anything to do with mod downloading?

EINVAL This one's sendfile64, a more efficient way to read bytes from one fd and write them to another. Pretty normal to try this and fail.

So yeah, that was a very disappointing exercise I'm afraid. :( I'll look in my colleague Tom in case he has any bright ideas and we'll see if Eric gives me anything to riff off of, I'll be sure to let you know if I think of anything else in the mean time.

  • Health 1

Share this comment


Link to comment
Share on other sites

Could you attach your appworkshop_457140.acf file?

Make a backup first and try deleting that file to see if it fixes it. This was the case for some users as mentioned in this bug report. It seems like your issue is slightly different as I don't see any I/O errors in my workshop_log.txt.

  • Like 1

Share this comment


Link to comment
Share on other sites

Thanks again to both of you for your help with this.

I ran "mv appworkshop_294100.acf appworkshop_294100.acf-tmp" and "mv appworkshop_457140.acf appworkshop_457140.acf-tmp" and reran the SteamCmd command. appworkshop_457140.acf got recreated and the command failed with the same error.

I'll attach all 3 files for your perusal.

appworkshop_457140.acf-tmp appworkshop_457140.acf appworkshop_294100.acf-tmp

Share this comment


Link to comment
Share on other sites

Try quitting Steam and deleting the cached folder in addition to the .acf file:

  • /home/arg/.local/share/Steam/steamapps/workshop/appworkshop_457140.acf
  • /home/arg/.local/share/Steam/steamapps/workshop/content/457140

 

Share this comment


Link to comment
Share on other sites

Sorry for the delay in getting back to you.

I went ahead, deleted the paths you specified and then used steamcmd and was met with the same problem:

Steam>workshop_download_item 457140 1717463209
Downloading item 1717463209 ...
ERROR! Download item 1717463209 failed (I/O Operation Failed).

Checked steam and still see the sizes showing "0B" too:

image.png.fad5819652dd1f41add6051c03786903.png

Share this comment


Link to comment
Share on other sites

I had the same issue as described above and was able to fix the issue by moving my workshop folder to an un-encrypted drive and creating a link in the original workshop directory pointing to the new un-encrypted one. The final relevant command wound up looking like this:
:~$ ln -s /media/gonzo/Mint1TB/unencrypted_workshop/457140 ~/.steam/steam/steamapps/workshop/content/457140
Hope this helps!

  • Thanks 2

Share this comment


Link to comment
Share on other sites

I was able to fix this error on YOMI hustle by going into /home/usr/.local/share/Steam/steamapps/workshop/content/ and deleting the entire directory named with the game's ID, then unsubscribing from every workshop content, clearing steam download cache, uninstalling the game, subscribing again and then installing the game back. Once the game is installed you will get an extra download for workshop content which for some reason takes way longer than usual for it's size, but once it's done, the mods will be properly installed!! Hope this helps any other folks who are experiencing the same bug for the workshop, for any game as well as oxygen not included.

Share this comment


Link to comment
Share on other sites

On 1/27/2025 at 4:49 AM, Gonzoalmighty said:

I had the same issue as described above and was able to fix the issue by moving my workshop folder to an un-encrypted drive and creating a link in the original workshop directory pointing to the new un-encrypted one. The final relevant command wound up looking like this:
:~$ ln -s /media/gonzo/Mint1TB/unencrypted_workshop/457140 ~/.steam/steam/steamapps/workshop/content/457140
Hope this helps!

Thank you so much it was driving me insane.

So for everybody else that stumbles upon this this is what I did:
(Disclaimer: As always do this at your own risk, don't trust commands from random people on the internet etc. etc.)
 

BEWARE: The paths might be different depending on your installation so please double check!!!

1. Close Steam

2. Remove Old Folders (as suggested by EricKlei already)
 

rm -rf ~/.steam/debian-installation/steamapps/workshop/content/457140
rm -f ~/.steam/debian-installation/steamapps/workshop/appworkshop_457140.acf

3. Setup

# Creates the directory and all parent directories (if they do not exist)
sudo mkdir -p /opt/steam_workshop/457140 
# Makes you the owner of the folder
sudo chown -R $USER:$USER /opt/steam_workshop
# Gives you full permission over the folder and everybody else read-only
chmod -R 775 /opt/steam_workshop
    
# create a simlink to your new folder (as suggested by Gonzoalmighty)
# ESPECIALLY HERE: BE AWARE OF PATH DIFFERENCES!
ln -s /opt/steam_workshop/457140 ~/.steam/debian-installation/steamapps/workshop/content/457140    





This should work. But as said above, check everything yourself before you run it.
 

Share this comment


Link to comment
Share on other sites



Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
  • Create New...