dawarich icon indicating copy to clipboard operation
dawarich copied to clipboard

undefined method 'y' for nil

Open ethronrion opened this issue 8 months ago • 17 comments

OS & Hardware Quad Core x86 CPU 2.3 GHz 4 GB RAM Ubuntu 22.04

Version 0.25.4 & 0.25.3

Describe the bug After the 0.25.3 update I had the "undefined method 'y' for nil" bug. I followed the instructions from the releases page and got the map working again https://github.com/Freika/dawarich/releases/tag/0.25.2

Today, when checking the map the error suddenly popped up again without me having done anything on the system. I tried updating to 0.25.4, but that didn't fix the issue either.

I ran the steps from the FAQ https://dawarich.app/docs/FAQ/#how-to-enter-dawarich-console but those didn't help either

To Reproduce Steps to reproduce the behavior:

  1. Go to '/map' or login
  2. See error

Expected behavior See the map

Screenshots Image

Additional context If you need me to provide more info, just let me know :)

ethronrion avatar Apr 08 '25 20:04 ethronrion

I am seeing the same issue. I have run the command to fix this several times. It consumes 9 gb of memory while running. It seemingly completes, but it still give me the error if I change date.

/var/app # bin/rails console
[dotenv] Set DATABASE_PORT
[dotenv] Loaded .env.development
Loading development environment (Rails 8.0.1)
[1] pry(main)> User.includes(:tracked_points).find_each do |user|
  user.tracked_points.where(lonlat: nil).update_all('lonlat = ST_SetSRID(ST_MakePoint(longitude, latitude), 4326)')
[1] pry(main)> User.includes(:tracked_points).find_each do |user|
  user.tracked_points.where(lonlat: nil).update_all('lonlat = ST_SetSRID(ST_MakePoint(longitude, latitude), 4326)')
D, [2025-04-08T21:34:25.420989 #33997] DEBUG -- :   User Load (5.1ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1000]]
D, [2025-04-08T21:35:40.962038 #33997] DEBUG -- :   Point Load (75009.3ms)  SELECT "points".* FROM "points" WHERE "points"."user_id" = $1  [["user_id", 1]]
D, [2025-04-08T21:37:17.199766 #33997] DEBUG -- :   Point Update All (31419.7ms)  UPDATE "points" SET lonlat = ST_SetSRID(ST_MakePoint(longitude, latitude), 4326) WHERE "points"."user_id" = $1 AND "points"."lonlat" IS NULL  [["user_id", 1]]
=> nil
[2] pry(main)>

I also get this on the "points" page

Showing /var/app/app/views/points/_point.html.erb where line #18 raised:
undefined method 'y' for nil

  def lat
    lonlat.y
  end

  private

larspehrsson avatar Apr 08 '25 21:04 larspehrsson

Disclaimer.. I don´t exactly know the datamodel in dawarich, so I don´t know if the procedure below will trash the information in latitude and longitude. Use it at your own risk.

I browsed the data, and I had 137,000 records where longitude and latitude were nil, but raw_data contained the information.

I ran this script to populate latitude and longitude from the raw_data

user = User.find_by(email: '[email protected]')

user.tracked_points.where(latitude: nil, longitude: nil).find_each do |point|
  raw = point.raw_data
  next unless raw.is_a?(Hash) && raw["lat"].present? && raw["lon"].present?

  point.latitude = raw["lat"]
  point.longitude = raw["lon"]
  point.save(validate: false)
end

And then I could run this to update the lonlat

rake data_cleanup:remove_duplicate_points
rake points:migrate_to_lonlat

some helper functions

user = User.find_by(email: '[email protected]')
user.tracked_points.where(latitude: nil, longitude: nil).size
user.tracked_points.where.not(latitude: nil, longitude: nil).where(lonlat: nil).size 

larspehrsson avatar Apr 09 '25 11:04 larspehrsson

@larspehrsson did it solve your issue? I can confirm the script you provided is a non-destructive one.

Freika avatar Apr 09 '25 22:04 Freika

Running the scripts didn't help. I still get the error.

[7] pry(main)> user.tracked_points.where(latitude: nil, longitude: nil).size
D, [2025-04-09T23:47:22.019364 #3301] DEBUG -- :   Point Count (1.1ms)  SELECT COUNT(*) FROM "points" WHERE "points"."user_id" = $1 AND "points"."latitude" IS NULL AND "points"."longitude" IS NULL  [["user_id", 1]]
=> 0
[8] pry(main)> user.tracked_points.where.not(latitude: nil, longitude: nil).where(lonlat: nil).size 
D, [2025-04-09T23:47:28.184180 #3301] DEBUG -- :   Point Count (561.5ms)  SELECT COUNT(*) FROM "points" WHERE "points"."user_id" = $1 AND NOT ("points"."latitude" IS NULL AND "points"."longitude" IS NULL) AND "points"."lonlat" IS NULL  [["user_id", 1]]
=> 1

hartmark avatar Apr 09 '25 23:04 hartmark

It did solve my issue. Maybe you, @Freika, could change the rake points:migrate_to_lonlat script to do something similar if there are records where the latitude and longitude are nil but the value is in the raw_data.

If you have just one record left, @hartmark, I would have a look at it with user.tracked_points.where.not(latitude: nil, longitude: nil).where(lonlat: nil) and then probably just destroy it if points.size is still just 1.

something like:

points = user.tracked_points.where.not(latitude: nil, longitude: nil).where(lonlat: nil)
points.size
# if still just one, delete it.
points.each(&:destroy)

There is a similar solution here https://github.com/Freika/dawarich/issues/973#issuecomment-2749558448

larspehrsson avatar Apr 10 '25 03:04 larspehrsson

It did solve my issue. Maybe you, @Freika, could change the rake points:migrate_to_lonlat script to do something similar if there are records where the latitude and longitude are nil but the value is in the raw_data.

If you have just one record left, @hartmark, I would have a look at it with user.tracked_points.where.not(latitude: nil, longitude: nil).where(lonlat: nil) and then probably just destroy it if points.size is still just 1.

something like:

points = user.tracked_points.where.not(latitude: nil, longitude: nil).where(lonlat: nil)
points.size
# if still just one, delete it.
points.each(&:destroy)

There is a similar solution here #973 (comment)

Cool, now it seems to be working properly for me.

hartmark avatar Apr 10 '25 11:04 hartmark

Is there a solution which is not messing around with scripts ?

EisernUnion avatar Apr 11 '25 11:04 EisernUnion

I tried @larspehrsson's approach and it didn't work, unfortunately. Still getting the same error when going back to the date where the error occurs. It doesn't seem to happen to new or current data, though

ethronrion avatar Apr 12 '25 14:04 ethronrion

I literally opened the database and edited the nulls. Fortunately, there were only a handful. In a graphic database app like Navicat or pgAdmin, you can see the raw values at the same time and copy/paste in the correct values. I would have written an update query, but for 11 it was just faster and easier to do it copy/paste. As soon as I did that, it worked great. No issues since. For some reason the Rails commands didn't get all the null values. If you're good at writing rails commands, you can probably work around the issue and find a suitable way to copy all the values into lonlat.

TheBig-O avatar Apr 12 '25 23:04 TheBig-O

@TheBig-O you copied values from raw_data, not longitude and `latitude? Were they empty?

Freika avatar Apr 13 '25 09:04 Freika

Yes, they were both empty in all eleven rows. It was weird to me too. I have database backups that I can probably mount somehow if you need me to pull those records. (I think... would take some creative thinking to start a container around a backup database.) The raw data has full values though.

TheBig-O avatar Apr 13 '25 15:04 TheBig-O

As soon as https://github.com/Freika/dawarich/releases/tag/0.25.5-rc0 is built, you can try using the freikin/dawarich:rc docker image to run Dawarich (just replace the image name in your compose file), it contains possible fix for the issue. The rake points:migrate_to_lonlat task now contains additional logic: it takes all points with empty longitude and latitude attrs and tries to fill them with appropriate data from the raw_data column.

The task might take some time and even be killed due to insufficient memory, but running it multiple times until it succeeds is a viable option.

Freika avatar Apr 13 '25 21:04 Freika

As soon as https://github.com/Freika/dawarich/releases/tag/0.25.5-rc0 is built, you can try using the freikin/dawarich:rc docker image to run Dawarich (just replace the image name in your compose file), it contains possible fix for the issue. The rake points:migrate_to_lonlat task now contains additional logic: it takes all points with empty longitude and latitude attrs and tries to fill them with appropriate data from the raw_data column.

The task might take some time and even be killed due to insufficient memory, but running it multiple times until it succeeds is a viable option.

Not sure if its related or not but on the RC version I get the following error when running it: Docker in Unraid.

/var/app # bin/rake points:migrate_to_lonlat
[dotenv] Loaded .env.development
Updating points to use lonlat...
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
D, [2025-04-14T12:03:51.835487 #124] DEBUG -- :   Point Load (6.0ms)  SELECT "points"."id", "points"."longitude", "points"."latitude", "points"."raw_data" FROM "points" WHERE "points"."longitude" IS NULL AND "points"."latitude" IS NULL ORDER BY "points"."id" ASC LIMIT $1  [["LIMIT", 1000]]
D, [2025-04-14T12:03:51.838711 #124] DEBUG -- :   ↳ lib/tasks/points.rake:10:in 'block (2 levels) in <main>'
rake aborted!
NoMethodError: undefined method '[]' for nil (NoMethodError)

    if point.raw_data['activitySegment']['waypointPath']['waypoints'][0]
                                        ^^^^^^^^^^^^^^^^
/var/app/app/services/points/raw_data_lonlat_extractor.rb:21:in 'Points::RawDataLonlatExtractor#extract_lonlat'
/var/app/app/services/points/raw_data_lonlat_extractor.rb:9:in 'Points::RawDataLonlatExtractor#call'
/var/app/lib/tasks/points.rake:11:in 'block (3 levels) in <main>'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:88:in 'Array#each'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:88:in 'block in ActiveRecord::Batches#find_each'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:172:in 'block in ActiveRecord::Batches#find_in_batches'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:461:in 'block in ActiveRecord::Batches#batch_on_unloaded_relation'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:434:in 'ActiveRecord::Batches#batch_on_unloaded_relation'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:289:in 'ActiveRecord::Batches#in_batches'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:171:in 'ActiveRecord::Batches#find_in_batches'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:87:in 'ActiveRecord::Batches#find_each'
/var/app/lib/tasks/points.rake:10:in 'block (2 levels) in <main>'
Tasks: TOP => points:migrate_to_lonlat
(See full trace by running task with --trace)
/var/app # 

toinopt avatar Apr 14 '25 11:04 toinopt

This is on the sidekiq container:

/var/app # bin/rake points:migrate_to_lonlat
[dotenv] Loaded .env.development
Updating points to use lonlat...
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
D, [2025-04-14T12:06:26.179490 #1049] DEBUG -- :    (6163.7ms)  REINDEX TABLE points;
D, [2025-04-14T12:06:26.179819 #1049] DEBUG -- :   ↳ lib/tasks/points.rake:8:in 'block (2 levels) in <main>'
D, [2025-04-14T12:06:26.180257 #1049] DEBUG -- :   TRANSACTION (0.2ms)  BEGIN
D, [2025-04-14T12:06:26.181799 #1049] DEBUG -- :   ↳ lib/tasks/points.rake:11:in 'block (3 levels) in <main>'
D, [2025-04-14T12:06:26.218483 #1049] DEBUG -- :    (18.4ms)  ALTER TABLE points DISABLE TRIGGER ALL;
D, [2025-04-14T12:06:26.220710 #1049] DEBUG -- :   ↳ lib/tasks/points.rake:11:in 'block (3 levels) in <main>'
D, [2025-04-14T12:06:26.335845 #1049] DEBUG -- :    (110.4ms)  UPDATE points
SET lonlat = ST_SetSRID(ST_MakePoint(longitude, latitude), 4326)::geography
WHERE lonlat IS NULL
  AND longitude IS NOT NULL
  AND latitude IS NOT NULL;

D, [2025-04-14T12:06:26.336190 #1049] DEBUG -- :   ↳ lib/tasks/points.rake:14:in 'block (3 levels) in <main>'
D, [2025-04-14T12:06:26.339218 #1049] DEBUG -- :   TRANSACTION (0.1ms)  ROLLBACK
D, [2025-04-14T12:06:26.350995 #1049] DEBUG -- :   ↳ lib/tasks/points.rake:10:in 'block (2 levels) in <main>'
rake aborted!
ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_points_on_lonlat_timestamp_user_id" (ActiveRecord::RecordNotUnique)
DETAIL:  Key (lonlat, "timestamp", user_id)=(0101000020E6100000FF78AF5A995821C0D099B4A9BA934340, 1744624450, 1) already exists.
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:160:in 'PG::Connection#exec'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:160:in 'ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements#perform_query'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:556:in 'block (2 levels) in ActiveRecord::ConnectionAdapters::DatabaseStatements#raw_execute'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract_adapter.rb:1011:in 'block in ActiveRecord::ConnectionAdapters::AbstractAdapter#with_raw_connection'
/var/app/vendor/bundle/ruby/3.4.0/gems/activesupport-8.0.1/lib/active_support/concurrency/null_lock.rb:9:in 'ActiveSupport::Concurrency::NullLock#synchronize'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract_adapter.rb:983:in 'ActiveRecord::ConnectionAdapters::AbstractAdapter#with_raw_connection'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:555:in 'block in ActiveRecord::ConnectionAdapters::DatabaseStatements#raw_execute'
/var/app/vendor/bundle/ruby/3.4.0/gems/activesupport-8.0.1/lib/active_support/notifications/instrumenter.rb:58:in 'ActiveSupport::Notifications::Instrumenter#instrument'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract_adapter.rb:1129:in 'ActiveRecord::ConnectionAdapters::AbstractAdapter#log'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:554:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#raw_execute'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:591:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#internal_execute'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:137:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#execute'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/query_cache.rb:27:in 'ActiveRecord::ConnectionAdapters::AbstractAdapter#execute'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:40:in 'ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements#execute'
/var/app/lib/tasks/points.rake:14:in 'block (3 levels) in <main>'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/transaction.rb:626:in 'block in ActiveRecord::ConnectionAdapters::TransactionManager#within_new_transaction'
/var/app/vendor/bundle/ruby/3.4.0/gems/activesupport-8.0.1/lib/active_support/concurrency/null_lock.rb:9:in 'ActiveSupport::Concurrency::NullLock#synchronize'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/transaction.rb:623:in 'ActiveRecord::ConnectionAdapters::TransactionManager#within_new_transaction'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:367:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#within_new_transaction'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:359:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#transaction'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/transactions.rb:234:in 'block in ActiveRecord::Transactions::ClassMethods#transaction'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:412:in 'ActiveRecord::ConnectionAdapters::ConnectionPool#with_connection'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_handling.rb:310:in 'ActiveRecord::ConnectionHandling#with_connection'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/transactions.rb:233:in 'ActiveRecord::Transactions::ClassMethods#transaction'
/var/app/lib/tasks/points.rake:10:in 'block (2 levels) in <main>'

Caused by:
PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_points_on_lonlat_timestamp_user_id" (PG::UniqueViolation)
DETAIL:  Key (lonlat, "timestamp", user_id)=(0101000020E6100000FF78AF5A995821C0D099B4A9BA934340, 1744624450, 1) already exists.
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:160:in 'PG::Connection#exec'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:160:in 'ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements#perform_query'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:556:in 'block (2 levels) in ActiveRecord::ConnectionAdapters::DatabaseStatements#raw_execute'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract_adapter.rb:1011:in 'block in ActiveRecord::ConnectionAdapters::AbstractAdapter#with_raw_connection'
/var/app/vendor/bundle/ruby/3.4.0/gems/activesupport-8.0.1/lib/active_support/concurrency/null_lock.rb:9:in 'ActiveSupport::Concurrency::NullLock#synchronize'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract_adapter.rb:983:in 'ActiveRecord::ConnectionAdapters::AbstractAdapter#with_raw_connection'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:555:in 'block in ActiveRecord::ConnectionAdapters::DatabaseStatements#raw_execute'
/var/app/vendor/bundle/ruby/3.4.0/gems/activesupport-8.0.1/lib/active_support/notifications/instrumenter.rb:58:in 'ActiveSupport::Notifications::Instrumenter#instrument'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract_adapter.rb:1129:in 'ActiveRecord::ConnectionAdapters::AbstractAdapter#log'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:554:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#raw_execute'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:591:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#internal_execute'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:137:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#execute'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/query_cache.rb:27:in 'ActiveRecord::ConnectionAdapters::AbstractAdapter#execute'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:40:in 'ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements#execute'
/var/app/lib/tasks/points.rake:14:in 'block (3 levels) in <main>'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/transaction.rb:626:in 'block in ActiveRecord::ConnectionAdapters::TransactionManager#within_new_transaction'
/var/app/vendor/bundle/ruby/3.4.0/gems/activesupport-8.0.1/lib/active_support/concurrency/null_lock.rb:9:in 'ActiveSupport::Concurrency::NullLock#synchronize'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/transaction.rb:623:in 'ActiveRecord::ConnectionAdapters::TransactionManager#within_new_transaction'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:367:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#within_new_transaction'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:359:in 'ActiveRecord::ConnectionAdapters::DatabaseStatements#transaction'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/transactions.rb:234:in 'block in ActiveRecord::Transactions::ClassMethods#transaction'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:412:in 'ActiveRecord::ConnectionAdapters::ConnectionPool#with_connection'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/connection_handling.rb:310:in 'ActiveRecord::ConnectionHandling#with_connection'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/transactions.rb:233:in 'ActiveRecord::Transactions::ClassMethods#transaction'
/var/app/lib/tasks/points.rake:10:in 'block (2 levels) in <main>'
Tasks: TOP => points:migrate_to_lonlat
(See full trace by running task with --trace)
/var/app # 

toinopt avatar Apr 14 '25 11:04 toinopt

Disclaimer.. I don´t exactly know the datamodel in dawarich, so I don´t know if the procedure below will trash the information in latitude and longitude. Use it at your own risk.

I browsed the data, and I had 137,000 records where longitude and latitude were nil, but raw_data contained the information.

I ran this script to populate latitude and longitude from the raw_data

user = User.find_by(email: '[email protected]')

user.tracked_points.where(latitude: nil, longitude: nil).find_each do |point|
  raw = point.raw_data
  next unless raw.is_a?(Hash) && raw["lat"].present? && raw["lon"].present?

  point.latitude = raw["lat"]
  point.longitude = raw["lon"]
  point.save(validate: false)
end

And then I could run this to update the lonlat

rake data_cleanup:remove_duplicate_points
rake points:migrate_to_lonlat

some helper functions

user = User.find_by(email: '[email protected]')
user.tracked_points.where(latitude: nil, longitude: nil).size
user.tracked_points.where.not(latitude: nil, longitude: nil).where(lonlat: nil).size 

After Running the commands provided here I don't get the nil error when opening the map.

toinopt avatar Apr 14 '25 11:04 toinopt

As soon as https://github.com/Freika/dawarich/releases/tag/0.25.5-rc0 is built, you can try using the freikin/dawarich:rc docker image to run Dawarich (just replace the image name in your compose file), it contains possible fix for the issue. The rake points:migrate_to_lonlat task now contains additional logic: it takes all points with empty longitude and latitude attrs and tries to fill them with appropriate data from the raw_data column. The task might take some time and even be killed due to insufficient memory, but running it multiple times until it succeeds is a viable option.

Not sure if its related or not but on the RC version I get the following error when running it: Docker in Unraid.

/var/app # bin/rake points:migrate_to_lonlat
[dotenv] Loaded .env.development
Updating points to use lonlat...
WARNING:  database "dawarich" has no actual collation version, but a version was recorded
D, [2025-04-14T12:03:51.835487 #124] DEBUG -- :   Point Load (6.0ms)  SELECT "points"."id", "points"."longitude", "points"."latitude", "points"."raw_data" FROM "points" WHERE "points"."longitude" IS NULL AND "points"."latitude" IS NULL ORDER BY "points"."id" ASC LIMIT $1  [["LIMIT", 1000]]
D, [2025-04-14T12:03:51.838711 #124] DEBUG -- :   ↳ lib/tasks/points.rake:10:in 'block (2 levels) in <main>'
rake aborted!
NoMethodError: undefined method '[]' for nil (NoMethodError)

    if point.raw_data['activitySegment']['waypointPath']['waypoints'][0]
                                        ^^^^^^^^^^^^^^^^
/var/app/app/services/points/raw_data_lonlat_extractor.rb:21:in 'Points::RawDataLonlatExtractor#extract_lonlat'
/var/app/app/services/points/raw_data_lonlat_extractor.rb:9:in 'Points::RawDataLonlatExtractor#call'
/var/app/lib/tasks/points.rake:11:in 'block (3 levels) in <main>'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:88:in 'Array#each'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:88:in 'block in ActiveRecord::Batches#find_each'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:172:in 'block in ActiveRecord::Batches#find_in_batches'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:461:in 'block in ActiveRecord::Batches#batch_on_unloaded_relation'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:434:in 'ActiveRecord::Batches#batch_on_unloaded_relation'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:289:in 'ActiveRecord::Batches#in_batches'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:171:in 'ActiveRecord::Batches#find_in_batches'
/var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.1/lib/active_record/relation/batches.rb:87:in 'ActiveRecord::Batches#find_each'
/var/app/lib/tasks/points.rake:10:in 'block (2 levels) in <main>'
Tasks: TOP => points:migrate_to_lonlat
(See full trace by running task with --trace)
/var/app # 

@joaoferreira-git let's try with the new version of dawarich:rc image, pull it and try again

Freika avatar Apr 15 '25 20:04 Freika

Same issue for me, get this screen when trying to log in after updating to 0.25.5 (latest) from yesterday

michaelcox12 avatar Apr 19 '25 20:04 michaelcox12

I have the same issue, even after running the script. I was able to find the '1 minute' having this issue. It is between 2025-04-13 18:32 and 2025-04-13 18:33

Is there a way I can find this record and correct it manually? running bin/rake points:migrate_to_lonlat does not fix this issue. I also tryed my data / points option, but it dies with the same error when I get to the same date

I am on version 0.27.1

Thanks

schneemaier avatar Jun 02 '25 03:06 schneemaier

@schneemaier @michaelcox12 @ethronrion check out this comment and the one below: https://github.com/Freika/dawarich/issues/1327#issuecomment-2945768831

Freika avatar Jun 06 '25 18:06 Freika

@schneemaier @michaelcox12 @ethronrion check out this comment and the one below: #1327 (comment)

Thank you! Looking at the referenced comment I understand what it is supposed to do. However I have no idea how to execute it, and unfortunatelly currently I don't have time to figure it out.

schneemaier avatar Jun 07 '25 03:06 schneemaier

Send a direct, specific message and I'll try to give you specific instructions. You need access to a database manager that can open the database file. From there, it is a relatively simple procedure.

TheBig-O avatar Jun 07 '25 04:06 TheBig-O

Send a direct, specific message and I'll try to give you specific instructions. You need access to a database manager that can open the database file. From there, it is a relatively simple procedure.

Hi @TheBig-O, I am not sure what you meant by direct specific message, but here is my setup: dawarich running in docker environment on debian. In this setup how should I access the database manager?

Thanks

schneemaier avatar Jun 08 '25 02:06 schneemaier

@schneemaier @michaelcox12 @ethronrion check out this comment and the one below: #1327 (comment)

Thank you! Looking at the referenced comment I understand what it is supposed to do. However I have no idea how to execute it, and unfortunatelly currently I don't have time to figure it out.

oh, you can run it in the console: https://dawarich.app/docs/FAQ/#how-to-enter-dawarich-console

Freika avatar Jun 08 '25 09:06 Freika

@schneemaier @michaelcox12 @ethronrion check out this comment and the one below: #1327 (comment)

Thank you! Looking at the referenced comment I understand what it is supposed to do. However I have no idea how to execute it, and unfortunatelly currently I don't have time to figure it out.

oh, you can run it in the console: https://dawarich.app/docs/FAQ/#how-to-enter-dawarich-console

Thank you! I tried it but ended up with error :(

user@server1:~/docker/dawarich# docker exec -it dawarich_app /bin/sh
# bin/rails console
[dotenv] Set DATABASE_PORT
[dotenv] Loaded .env.development


Type 'jobs_help' to see how to connect to the available job servers to manage jobs

Loading development environment (Rails 8.0.2)
[1] pry(main)> Point.where(lonlat: nil).each do |p|
[1] pry(main)>   p.update(longitude: p.raw_data['lon'], latitude: p.raw_data['lat'], lonlat: "POINT(#{raw_data['lon']} #{p.raw_data['lat']})")
[1] pry(main)> end
  Point Load (10340.8ms)  SELECT "points".* FROM "points" WHERE "points"."lonlat" IS NULL
NameError: undefined local variable or method 'raw_data' for main (NameError)
from (pry):2:in 'block in __pry__'
[2] pry(main)>

But when i change the command to

Point.where(lonlat: nil).each do |p|
   print p
end

I get exaclty 1 record which do have raw_data field

  Point Load (109.1ms)  SELECT "points".* FROM "points" WHERE "points"."lonlat" IS NULL
#<Point:0x00007efe855bf8d0>=> [#<Point:0x00007efe855bf8d0
  id: 5017388,
  battery_status: "charging",
  ping: nil,
  battery: 45,
  tracker_id: "ba",
  topic: "owntracks/user/xxxxxx",
  altitude: 309,
  longitude: nil,
  velocity: "0.0",
  trigger: "background_event",
  bssid: "xxxxxx",
  ssid: "XXXXX",
  connection: "wifi",
  vertical_accuracy: 1,
  accuracy: 12,
  timestamp: 1744583500,
  latitude: nil,
  mode: nil,
  inrids: nil,
  in_regions: nil,
  raw_data:
   {"m" => 1, "t" => "p", "bs" => 2, "_id" => "5e9d2c60", "acc" => 12, "alt" => xxx, "cog" => 0, "lat" => xx.0030078, "lon" => yy.6264634, "tid" => "ba", "tst" => 1744583500, "vac" => 1, "vel" => 0, "SSID" => "xxxxxxx", "batt" => 45, "conn" => "w", "BSSID" => "xxxxxxxx", "_type" => "location", "point" => {"topic" => "owntracks/user/xxxxxx", "created_at" => 1744585334}, "topic" => "owntracks/user/xxxxxx", "action" => "create", "api_key" => "xxx", "controller" => "api/v1/owntracks/points", "created_at" => 1744585334},
  import_id: nil,
  city: "x",
  country: "x",
  created_at: "2025-04-13 19:06:55.155852000 -0400",
  updated_at: "2025-04-13 19:07:02.968999000 -0400",
  user_id: 1,
  geodata:
   {"type" => "Feature", "geometry" => {"type" => "Point", "coordinates" => [xx.62643580164813, xx.0029069]}, "properties" => {"city" => "xxx", "type" => "house", "state" => "xxx", "county" => "xxxx", "extent" => [xx.626536, xx.0029969, xx.6263356, xx.0028268], "osm_id" => 245134195, "street" => "xx", "country" => "xx", "osm_key" => "building", "locality" => "xx", "osm_type" => "x", "postcode" => "xx", "osm_value" => "house", "countrycode" => "x", "housenumber" => "x"}},
  visit_id: nil,
  reverse_geocoded_at: "2025-04-13 19:07:02.779361000 -0400",
  course: nil,
  course_accuracy: nil,
  external_track_id: nil,
  lonlat: nil,
  country_id: nil>]

I am currently running version 0.27.4

schneemaier avatar Jun 09 '25 01:06 schneemaier

@schneemaier there was a typo in my code, here's the corrected version:

Point.where(lonlat: nil).each do |p|
  p.update(longitude: p.raw_data['lon'], latitude: p.raw_data['lat'], lonlat: "POINT(#{p.raw_data['lon']} #{p.raw_data['lat']})")
end

Freika avatar Jun 09 '25 09:06 Freika

@Freika Thank you, but something is still not working. It finds the point but does not apply the changes, instead I get a rollback notification in the output.

[1] pry(main)> Point.where(lonlat: nil).each do |p|
[1] pry(main)>   p.update(longitude: p.raw_data['lon'], latitude: p.raw_data['lat'], lonlat: "POINT(#{p.raw_data['lon']} #{p.raw_data['lat']})")
[1] pry(main)> end
  Point Load (137.7ms)  SELECT "points".* FROM "points" WHERE "points"."lonlat" IS NULL
  TRANSACTION (0.3ms)  BEGIN
  Point Exists? (1.9ms)  SELECT 1 AS one FROM "points" WHERE "points"."lonlat" = $1 AND "points"."id" != $2 AND "points"."timestamp" = $3 AND "points"."user_id" = $4 LIMIT $5  [["lonlat", "[FILTERED]"], ["id", 5017388], ["timestamp", 1744583500], ["user_id", 1], ["LIMIT", 1]]
  TRANSACTION (0.4ms)  ROLLBACK
=> [#<Point:0x00007f8d535feb68
  longitude: [FILTERED],
  latitude: [FILTERED],
  lonlat: [FILTERED],
  user_id: 1,
  timestamp: 1744583500,
  id: 5017388,
  battery_status: "charging",
  ping: nil,
  battery: 45,
  tracker_id: "ba",
  topic: "owntracks/user/shiba",
  altitude: 309,
  velocity: "0.0",
  trigger: "background_event",
  bssid: "xxxx",
  ssid: "xxxx",
  connection: "wifi",
  vertical_accuracy: 1,
  accuracy: 12,
  mode: nil,
  inrids: nil,
  in_regions: nil,
  raw_data:
   {"m" => 1, "t" => "p", "bs" => 2, "_id" => "5e9d2c60", "acc" => 12, "alt" => 309, "cog" => 0, "lat" => xx.0030078, "lon" => -xx.6264634, "tid" => "ba", "tst" => 1744583500, "vac" => 1, "vel" => 0, "SSID" => "xxxx", "batt" => 45, "conn" => "w", "BSSID" => "xxxx", "_type" => "location", "point" => {"topic" => "owntracks/user/shiba", "created_at" => 1744585334}, "topic" => "owntracks/user/shiba", "action" => "create", "api_key" => "xxxxx", "controller" => "api/v1/owntracks/points", "created_at" => 1744585334},
  import_id: nil,
  city: "xx",
  country: "xx",
  created_at: "2025-04-13 19:06:55.155852000 -0400",
  updated_at: "2025-04-13 19:07:02.968999000 -0400",
  geodata:
   {"type" => "Feature", "geometry" => {"type" => "Point", "coordinates" => [-xx.62643580164813, xx.0029069]}, "properties" => {"city" => "xxxx", "type" => "house", "state" => "xxx", "county" => "xxxx", "extent" => [-xx.626536, xx.0029969, -xx.6263356, xx.0028268], "osm_id" => 245134195, "street" => "xxxx", "country" => "xxxxx", "osm_key" => "building", "locality" => "xxxx", "osm_type" => "W", "postcode" => "xxxx", "osm_value" => "house", "countrycode" => "XX", "housenumber" => "XX"}},
  visit_id: nil,
  reverse_geocoded_at: "2025-04-13 19:07:02.779361000 -0400",
  course: nil,
  course_accuracy: nil,
  external_track_id: nil,
  country_id: nil>]

schneemaier avatar Jun 09 '25 12:06 schneemaier

Could it be that you have to pass the numbers as strings? I started using Dawarich just yesterday and had a similar issue, and then noticed in the GPSLogger instructions there are quotes around the numeric values.

What I'm using now on Dawarich 0.27.4 has this structure:

{
    "_type": "location",
    "t": "u",
    "acc": str(data["acc"]),
    "alt": str(data["alt"]),
    "batt": str(data["batt"]),
    "bs": str(data["bs"]),
    "lat": str(data["lat"]),
    "lon": str(data["lon"]),
    "tst": str(data["tst"]),
    "vel": str(data["vel"]),
}

(this is python code because I have a middleware forwarding from GPSLogger calls, but here is just copying from the message and converting back to string).

Looks like if the value is invalid you still get an HTTP 200 but then it gives this error processing the message. I don't know Ruby and can't really follow the process, but I assume it's placing the message raw in a queue and processing it later, I can see it in the postgres table.

jacopofar avatar Jun 09 '25 16:06 jacopofar

Could it be that you have to pass the numbers as strings?

I use owntracks to get my location data and that one does not need any special setup. I only have 1 record which is broken, and trying to figure out why the "repair" script is failing.

schneemaier avatar Jun 09 '25 17:06 schneemaier

@schneemaier let's use more explicit version:

Point.where(lonlat: nil).each do |p|
  p.update!(longitude: p.raw_data['lon'], latitude: p.raw_data['lat'], lonlat: "POINT(#{p.raw_data['lon']} #{p.raw_data['lat']})")
end

The only change is we're using update! with bang sign, it will explicitly throw an error instead of silently rolling back the transaction

Freika avatar Jun 09 '25 17:06 Freika

@schneemaier let's use more explicit version:

Point.where(lonlat: nil).each do |p| p.update!(longitude: p.raw_data['lon'], latitude: p.raw_data['lat'], lonlat: "POINT(#{p.raw_data['lon']} #{p.raw_data['lat']})") end The only change is we're using update! with bang sign, it will explicitly throw an error instead of silently rolling back the transaction

Okay, so the error is suggesting duplicate record?

ActiveRecord::RecordInvalid: Validation failed: Lonlat already has a point at this location and time for this user (ActiveRecord::RecordInvalid)
from /var/app/vendor/bundle/ruby/3.4.0/gems/activerecord-8.0.2/lib/active_record/validations.rb:87:in 'ActiveRecord::Validations#raise_validation_error'

schneemaier avatar Jun 09 '25 17:06 schneemaier