Connection not working on initial setup

When I try to manually set up a Stash connection, I get the following error:

Error connecting

Unable to connect to the server.

Could not connect to the server.

I have this issue on Apple TV and on an iPad. I’ve checked the IP address and port and it matches exactly what it should be and when I go to that IP:port in Safari, it works fine. Authentication in Stash is turned off, but I’ve tried to toggle it on and off and it doesn’t function either way. When authentication is turned on, Mirage pulls the correct API key so it seems to get some connection. My Stash instance is run as a docker container on Unraid.

That’s not a very useful error message, is it? :slight_smile:

If Safari is able to see Stash and Mirage is able to retrieve the API key, then it should connect normally.

Look in Settings > Diagnostics > Error Log. If there are any entries there, it should provide further detail about why the connection is failing. Send a photo or a transcribed text of each entry to: support@mirageplayer.app. Alternatively you can reply with them here.

Also,

  • Is the Stash server running in SFW mode?
  • Are you using SSL? If so, are the certificates self-signed?
  • Is there any kind of proxy in front of Stash?
  • From Safari can you connect and see the GraphQL playground at <http_server_host:port>/playground?
  • On the Stash server in Settings > Logs, does anything show up when you try to connect using Mirage?

A last resort, but useful to try: enable Stash’s DLNA support, and try to connect using that in Mirage. Just add it as another Server: Settings > Find a server… That screen should find Stash automatically. Save the DLNA server and see if you can browse content. This is only a test and it is a much more limited view of your library than Stash allows. You can delete the DLNA server after this. If you can connect using DLNA then that is useful information to help diagnose this problem.

The upcoming 2.0 release has much better logging and debugging support. If you’d like to participate in the beta program, let me know your email address and I’ll send you a TestFlight invite.

///

Unfortunately, you can’t access the settings dialog until after you have set up a server. I set up a SMB connection so that I could get to the settings.

The error is as follows:

Source: MiragePlayer/SettingsView.swift:531

message: connecting failed with error: HTTP Error: Request timed out.

  • Server is not in SFW mode.
  • No SSL
  • No proxy
  • Yes, I can connect to <http_server_host:port>/playground on Safari
  • Here are the Stash logs:
026-07-23 14:55:17
Trace   
SQL [106.054µs]: SELECT COALESCE(SUM(`video_files`.`duration`), 0) FROM `scenes` INNER JOIN `scenes_files` ON (`scenes_files`.`scene_id` = `scenes`.`id`) INNER JOIN `video_files` ON (`video_files`.`file_id` = `scenes_files`.`file_id`), args: []
2026-07-23 14:55:13
Trace   
SQL [170.398µs]: SELECT `scenes`.*, `scenes_files`.`file_id` AS `primary_file_id`, `folders`.`path` AS `primary_file_folder_path`, `files`.`basename` AS `primary_file_basename`, `fingerprint_md5`.`fingerprint` AS `primary_file_checksum`, `fingerprint_oshash`.`fingerprint` AS `primary_file_oshash` FROM `scenes` LEFT JOIN `scenes_files` ON ((`scenes_files`.`scene_id` = `scenes`.`id`) AND (`scenes_files`.`primary` = ?)) LEFT JOIN `files` ON (`files`.`id` = `scenes_files`.`file_id`) LEFT JOIN `folders` ON (`folders`.`id` = `files`.`parent_folder_id`) LEFT JOIN `files_fingerprints` AS `fingerprint_md5` ON ((`fingerprint_md5`.`file_id` = `scenes_files`.`file_id`) AND (`fingerprint_md5`.`type` = ?)) LEFT JOIN `files_fingerprints` AS `fingerprint_oshash` ON ((`fingerprint_oshash`.`file_id` = `scenes_files`.`file_id`) AND (`fingerprint_oshash`.`type` = ?)) WHERE (`scenes`.`id` IN (?)), args: [1 md5 oshash 1854914]
2026-07-23 14:55:13
Debug   
SLOW SQL [460.535262ms]: SELECT DISTINCT scenes.id FROM scenes ORDER BY scenes.updated_at DESC, COALESCE(scenes.title, scenes.id) COLLATE NATURAL_CI ASC LIMIT 1 OFFSET 0 , args: []
2026-07-23 14:55:12
Trace   
SQL [169.307µs]: SELECT `galleries`.*, `galleries_files`.`file_id` AS `primary_file_id`, `folders`.`path` AS `primary_file_folder_path`, `files`.`basename` AS `primary_file_basename`, `gallery_folder`.`path` AS `folder_path` FROM `galleries` LEFT JOIN `galleries_files` ON ((`galleries_files`.`gallery_id` = `galleries`.`id`) AND (`galleries_files`.`primary` = ?)) LEFT JOIN `files` ON (`files`.`id` = `galleries_files`.`file_id`) LEFT JOIN `folders` ON (`folders`.`id` = `files`.`parent_folder_id`) LEFT JOIN `folders` AS `gallery_folder` ON (`gallery_folder`.`id` = `galleries`.`folder_id`) WHERE (`galleries`.`id` IN (?)), args: [1 6589]
2026-07-23 14:55:12
Trace   
SQL [45.202555ms]: SELECT DISTINCT galleries.id FROM galleries ORDER BY galleries.updated_at DESC, COALESCE(galleries.title, galleries.id) COLLATE NATURAL_CI ASC LIMIT 1 OFFSET 0 , args: []
2026-07-23 14:55:12
Trace   
SQL [18.733382ms]: SELECT COUNT(*) as count FROM (SELECT DISTINCT galleries.id FROM galleries) as temp, args: []
2026-07-23 14:55:12
Trace   
SQL [230.443µs]: SELECT COALESCE(SUM(`files`.`size`), 0) FROM `scenes` INNER JOIN `scenes_files` ON (`scenes`.`id` = `scenes_files`.`scene_id`) INNER JOIN `files` ON (`scenes_files`.`file_id` = `files`.`id`), args: []
2026-07-23 14:55:12
Trace   
SQL [91.474µs]: SELECT * FROM "performers" WHERE ("performers"."id" IN (13795)), args: []
2026-07-23 14:55:12
Trace   
SQL [7.426395ms]: SELECT DISTINCT performers.id FROM performers ORDER BY performers.updated_at DESC, COALESCE(performers.name, performers.id) COLLATE NATURAL_CI ASC LIMIT 1 OFFSET 0 , args: []
2026-07-23 14:55:12
Trace   
SQL [40.351µs]: SELECT `groups`.* FROM `groups` WHERE (`groups`.`id` IN (?)), args: [7059]
2026-07-23 14:55:12
Trace   
SQL [8.10761ms]: SELECT DISTINCT groups.id FROM groups ORDER BY groups.updated_at DESC, COALESCE(groups.name, groups.id) COLLATE NATURAL_CI ASC LIMIT 1 OFFSET 0 , args: []
2026-07-23 14:55:12
Trace   
SQL [55.692µs]: SELECT `tags`.* FROM `tags` WHERE (`tags`.`id` IN (?)), args: [1655]
2026-07-23 14:55:12
Trace   
SQL [680.112µs]: SELECT DISTINCT tags.id FROM tags ORDER BY tags.updated_at DESC, COALESCE(tags.sort_name, tags.name, tags.id) COLLATE NATURAL_CI ASC LIMIT 1 OFFSET 0 , args: []
2026-07-23 14:55:12
Trace   
SQL [336.872µs]: SELECT COUNT(*) as count FROM (SELECT DISTINCT tags.id FROM tags) as temp, args: []
2026-07-23 14:55:12
Trace   
SQL [5.653055ms]: SELECT COUNT(*) as count FROM (SELECT DISTINCT performers.id FROM performers) as temp, args: []
2026-07-23 14:55:12
Trace   
SQL [91.018µs]: SELECT `studios`.* FROM `studios` WHERE (`studios`.`id` IN (?)), args: [1919]
2026-07-23 14:55:12
Trace   
SQL [1.292964ms]: SELECT DISTINCT studios.id FROM studios ORDER BY studios.updated_at DESC, COALESCE(studios.name, studios.id) COLLATE NATURAL_CI ASC LIMIT 1 OFFSET 0 , args: []
2026-07-23 14:55:12
Trace   
SQL [1.798991ms]: SELECT COUNT(*) as count FROM (SELECT DISTINCT groups.id FROM groups) as temp, args: []
2026-07-23 14:55:12
Trace   
SQL [1.107539ms]: SELECT COUNT(*) as count FROM (SELECT DISTINCT studios.id FROM studios) as temp, args: []
2026-07-23 14:55:12
Trace   
SQL [42.211µs]: SELECT `saved_filters`.* FROM `saved_filters` WHERE (`saved_filters`.`mode` = ?) ORDER BY `saved_filters`.`name` ASC, args: [TAGS]
2026-07-23 14:55:12
Trace   
SQL [101.327µs]: SELECT `saved_filters`.* FROM `saved_filters` WHERE (`saved_filters`.`mode` = ?) ORDER BY `saved_filters`.`name` ASC, args: [IMAGES]
2026-07-23 14:55:12
Trace   
SQL [53.291µs]: SELECT COUNT(*) FROM `scenes`, args: []
2026-07-23 14:55:12
Trace   
SQL [115.225µs]: SELECT `saved_filters`.* FROM `saved_filters` WHERE ((`saved_filters`.`mode` = ?) OR (`saved_filters`.`mode` = ?)) ORDER BY `saved_filters`.`name` ASC, args: [GROUPS MOVIES]
2026-07-23 14:55:12
Trace   
SQL [50.908µs]: SELECT `saved_filters`.* FROM `saved_filters` WHERE (`saved_filters`.`mode` = ?) ORDER BY `saved_filters`.`name` ASC, args: [GALLERIES]
2026-07-23 14:55:12
Trace   
SQL [63.833µs]: SELECT `saved_filters`.* FROM `saved_filters` WHERE (`saved_filters`.`mode` = ?) ORDER BY `saved_filters`.`name` ASC, args: [SCENES]
2026-07-23 14:55:12
Trace   
SQL [103.455µs]: SELECT `saved_filters`.* FROM `saved_filters` WHERE (`saved_filters`.`mode` = ?) ORDER BY `saved_filters`.`name` ASC, args: [PERFORMERS]
2026-07-23 14:55:12
Trace   
SQL [115.06µs]: SELECT `saved_filters`.* FROM `saved_filters` WHERE (`saved_filters`.`mode` = ?) ORDER BY `saved_filters`.`name` ASC, args: [STUDIOS]

Weirdly, the DLNA server is never found even after I verified it was specifically enabled in Stash. Looking at it, it seems Stash may be crashing when I enable DLNA.

I’ll send my email address in a DM or to that email you posted.

Oh duh, the DLNA issue was because I used XBVR DLNA to get to the MiragePlayer settings and didn’t turn it off before enabling Stash.

With it correctly enabled, MiragePlayer doesn’t find it either but VLC on iPad does

Looks like my global whitelist allow for IPs on DLNA was not functioning and Mirage picked up the DLNA server once I explicitly allowed it.

As far as I can tell, this timeout indicates that the initial handshake to Stash is taking longer than the 5s allowed. This is done so that Mirage can display an error message that it can’t connect instead of hanging for 30s (the normal timeout). Oddly this call isn’t used when fetching the API key so it works.

This first real API call should return almost instantaneously, but the backing query can be complex depending on the library and configuration. I’ve drastically improved this one query in 2.0, but my guess is in 1.1 that it’s a combination of (1) running in a Docker container may slow network processing down so the 5s is too low of a timeout and/or (2) you may have a library with lots of saved filters.

I’m not sure how to get more info from here without diving into more logging. We can definitely determine the root cause with the beta though.

///

Using the v2 app worked first time (didn’t even have to reconfigure the server)

Awesome!

I’ve been working on 2.0 for a while now and I’m itching to release it. Barring any bad bugs we find and Apple’s cooperation, it should be out soon.