Hello All,
I have an error with a product inventory levels options.
If I go to the product and click on ‘edit’ and then the tab ‘inventory levels’ I get this error:
any idea?
Hello All,
I have an error with a product inventory levels options.
If I go to the product and click on ‘edit’ and then the tab ‘inventory levels’ I get this error:
any idea?
Stacktrace follows:
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [org.pih.warehouse.core.Location#5523cb3c8db72f51018dbd29e49c0003]
at gsp_openboxes_product_inventoryLevels_gsp$_run_closure2_closure4.doCall(gsp_openboxes_product_inventoryLevels_gsp.groovy:85)
at gsp_openboxes_product_inventoryLevels_gsp$_run_closure2.doCall(gsp_openboxes_product_inventoryLevels_gsp.groovy:57)
at gsp_openboxes_product_inventoryLevels_gsp$_run_closure2.doCall(gsp_openboxes_product_inventoryLevels_gsp.groovy)
at gsp_openboxes_product_inventoryLevels_gsp.run(gsp_openboxes_product_inventoryLevels_gsp.groovy:161)
at org.pih.warehouse.product.ProductController$_closure11.doCall(ProductController.groovy:226)
at org.pih.warehouse.product.ProductController$_closure11.doCall(ProductController.groovy)
at grails.plugin.springcache.web.GrailsFragmentCachingFilter.doFilter(GrailsFragmentCachingFilter.groovy:66)
at net.sf.ehcache.constructs.web.filter.Filter.doFilter(Filter.java:86)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:622)
at java.lang.Thread.run(Thread.java:748)
2025-03-26 12:07:08,043 [http-bio-8443-exec-340] INFO filters.SecurityFilters - errors.handleNotFound: [user:admin, location:Centraal Magazijn District]
2025-03-26 12:07:08,044 [http-bio-8443-exec-340] INFO filters.SecurityFilters - No rule for errors:handleNotFound -> allow anonymous
2025-03-26 12:07:08,044 [http-bio-8443-exec-340] INFO core.ErrorsController - Params [templateName:inventoryLevels, id:5523c3127e750eb9017e8d0756750041, action:handleNotFound, controller:errors]
2025-03-26 12:07:08,046 [http-bio-8443-exec-340] INFO filters.SecurityFilters - Request duration for (errors/handleNotFound): 2ms/0ms
2025-03-26 12:07:08,046 [http-bio-8443-exec-340] INFO filters.SecurityFilters - Request for (errors/handleNotFound) failed with an uncaught exception: Executing action [renderTemplate] of controller [org.pih.warehouse.product.ProductController] caused exception: Error executing tag <g:form>: No row with the given identifier exists: [org.pih.warehouse.core.Location#5523cb3c8db72f51018dbd29e49c0003] at /WEB-INF/grails-app/views/product/_inventoryLevels.gsp:128
This is going to be similar to the other issue you encountered in which an object was deleted from the database. Here, the app is trying to retrieve inventory levels for the given product and it’s encountering an inventory level for a location that has been deleted.
This should have been prevented by a foreign key constraint, but the inventory levels are associated with inventory records (not locations) so it’s possible the inventory record still exists and the location has been deleted.
To figure out if this is true you can run the following query and then delete the offending inventory level(s) and inventory records.
select *
from inventory_level
join inventory on inventory.id = inventory_level.
left outer join location on location.inventory_id = inventory.id
where product_id = '<product_id>' and location.id is null
Aside: Ideally, we’d cascade the delete from location to inventory, inventory levels, etc, but this is a very destructive operation so we’ve taken an approach where we use foreign key constraints to prevent deleting and put the onus of cascading the delete onto the administration. I don’t like deleting data because once data has been added it could potentially be in a lot of other places (including reporting tables) and the process to delete should require a thoughtful analysis by an administrator. But we should have a way for confident admins to completely delete objects in the system (either soft or hard) so apologies for the inconvenience.
If that doesn’t work, then it’s possibly one of the other foreign key columns in inventory level. Here’s what the inventory level table looks like.
MariaDB [openboxes]> describe inventory_level;
+---------------------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------------+---------------+------+-----+---------+-------+
| id | char(38) | NO | PRI | | |
| version | bigint(20) | NO | | NULL | |
| inventory_id | char(38) | YES | MUL | NULL | |
| min_quantity | int(11) | YES | | NULL | |
| product_id | char(38) | YES | MUL | NULL | |
| reorder_quantity | int(11) | YES | | NULL | |
| date_created | datetime | YES | | NULL | |
| last_updated | datetime | YES | | NULL | |
| status | varchar(255) | YES | | NULL | |
| max_quantity | int(11) | YES | | NULL | |
| bin_location | varchar(255) | YES | | NULL | |
| abc_class | varchar(255) | YES | | NULL | |
| preferred | tinyint(4) | YES | | NULL | |
| expected_lead_time_days | decimal(19,2) | YES | | NULL | |
| forecast_period_days | decimal(19,2) | YES | | NULL | |
| forecast_quantity | decimal(19,2) | YES | | NULL | |
| preferred_bin_location_id | char(38) | YES | MUL | NULL | |
| replenishment_location_id | char(38) | YES | MUL | NULL | |
| comments | varchar(255) | YES | | NULL | |
| internal_location_id | char(38) | YES | MUL | NULL | |
| replenishment_period_days | decimal(19,2) | YES | | NULL | |
| demand_time_period_days | decimal(19,2) | YES | | NULL | |
+---------------------------+---------------+------+-----+---------+-------+
22 rows in set (0.002 sec)
So you would want to find any inventory levels where one of the location foreign key columns is set to the missing location.
select *
from inventory_level
where internal_location_id = '5523cb3c8db72f51018dbd29e49c0003'
or preferred_bin_location_id = '5523cb3c8db72f51018dbd29e49c0003'
or replenishment_location_id = '5523cb3c8db72f51018dbd29e49c0003'
If this query returns a record, you should be able to NULL out the location ID foreign key
update inventory_level
set <location_id> = NULL
where <location_id> = '5523cb3c8db72f51018dbd29e49c0003'
Or delete the inventory level.
delete from inventory_level where id in (
select id
from inventory_level
where internal_location_id = '5523cb3c8db72f51018dbd29e49c0003'
or preferred_bin_location_id = '5523cb3c8db72f51018dbd29e49c0003'
or replenishment_location_id = '5523cb3c8db72f51018dbd29e49c0003'
)
Note: Please don’t trust the SQL above, especially the DML statements that change data. Check and double check the SQL. And ideally, run these statements on a backup of the database first.
Hmm yeah I deleted the inventory level for that product. Now it works.
Any idea how this can happen?
Did you delete the location tied to that inventory level?