laurent22 / joplin

Joplin - the privacy-focused note taking app with sync capabilities for Windows, macOS, Linux, Android and iOS.
https://joplinapp.org
Other
46.01k stars 5k forks source link

Some items cannot be synchronized. #10904

Closed victor03303 closed 1 month ago

victor03303 commented 2 months ago

Operating system

iOS

Joplin version

Joplin 13.0.7

Desktop version info

No response

Current behaviour

All of the sudden i got this message. Not sure what caused it or how to reproduce. Also on my iphone i don’t get this error message, nor on my Linux clients. Just the tablet that throws this error. Ipados 17.5.1 Ipad pro 11 2nd generation

Expected behaviour

To sync without errors

Logs

07-16T23:55:38: Synchronizer: Could not refresh lock - cancelling sync. Error was: Error: Lock has expired Code: lockExpired Error: Lock has expired at construct (native) at apply (native) at _construct (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:309103:28) at Wrapper (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:309067:46) at construct (native) at _createSuperInternal (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:309028:294) at call (native) at JoplinError (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:309042:26) at ?anon0 (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:325604:67) at next (native) at fulfilled (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:325246:30) at tryCallOne (address at InternalBytecode.js:1:1180) at anonymous (address at InternalBytecode.js:1:1874) at apply (native) at anonymous (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:14614:26) at _callTimer (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:14503:17) at _callReactNativeMicrotasksPass (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:14541:17) at callReactNativeMicrotasks (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:14744:44) at callReactNativeMicrotasks (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:3572:48) at anonymous (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:3436:45) at guard (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:3544:15) at flushedQueue (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:3435:21) at invokeCallbackAndReturnFlushedQueue (/Users/laurent/Library/Developer/Xcode/DerivedData/Joplin-hgodvgxrovwfvickonvnbzuehodc/Build/Intermediates.noindex/ArchiveIntermediates/Joplin/BuildProductsPath/Release-iphoneos/main.jsbundle:3429:33)

laurent22 commented 2 months ago

What happens if you try again now? This lock should expire and sync should resume normally

victor03303 commented 2 months ago

I found the button retry all. When pressing the button it changes color but nothing seems to happen.

So i pressed the 'synchronise' button after, but the error banner remains

image

image

image

Captain-Barge commented 2 months ago

I am having a very similar issue on Android, except without the "some items can't be synchronized" message. I planned to open a new issue, but this one seems similar enough that I'll drop the info here instead.

Specs

Observations

Things I've tried

Log messages

Errors-only option Note that after a fresh Joplin install, login to Joplin Cloud, and a sync, I put in the wrong e2ee master password on purpose just to see what would happen. It said that the password was wrong. So I corrected it. Not sure if that will manifest in the log or not, but I wanted to mention it.

08-25T14:22:33: JoplinServerApi: Code: 08-25T14:22:33: JoplinServerApi: TypeError: Network request failed TypeError: Network request failed at anonymous (address at index.android.bundle:1:318538) at apply (native) at anonymous (address at index.android.bundle:1:286244) at _callTimer (address at index.android.bundle:1:285542) at callTimers (address at index.android.bundle:1:287310) at apply (native) at callFunction (address at index.android.bundle:1:148905) at anonymous (address at index.android.bundle:1:147210) at guard (address at index.android.bundle:1:148166) at callFunctionReturnFlushedQueue (address at index.android.bundle:1:147168) 08-25T14:22:33: JoplinServerApi: curl -v -X GET -H "X-API-AUTH: **" -H "X-API-MIN-VERSION: 2.6.0" 'https://api.joplincloud.com/api/items/root:/d15fca351add49078060816d0e3c970d.md:/content' 08-25T13:41:47: Synchronizer: Could not refresh lock - cancelling sync. Error was: Error: Lock has expired Code: lockExpired Error: Lock has expired at construct (native) at Wrapper (address at index.android.bundle:1:2747690) at construct (native) at _createSuperInternal (address at index.android.bundle:1:2746826) at call (native) at JoplinError (address at index.android.bundle:1:2747154) at ?anon0 (address at index.android.bundle:1:3033348) at next (native) at fulfilled (address at index.android.bundle:1:3029007) at tryCallOne (address at InternalBytecode.js:1:1180) at anonymous (address at InternalBytecode.js:1:1874) at apply (native) at anonymous (address at index.android.bundle:1:286591) at _callTimer (address at index.android.bundle:1:285542) at _callReactNativeMicrotasksPass (address at index.android.bundle:1:285686) at callReactNativeMicrotasks (address at index.android.bundle:1:287676) at callReactNativeMicrotasks (address at index.android.bundle:1:148328) at anonymous (address at index.android.bundle:1:147412) at guard (address at index.android.bundle:1:148166) at flushedQueue (address at index.android.bundle:1:147323) at invokeCallbackAndReturnFlushedQueue (address at index.android.bundle:1:147266) 08-25T13:31:53: Synchronizer: Could not refresh lock - cancelling sync. Error was: Error: Lock has expired Code: lockExpired Error: Lock has expired at construct (native) at Wrapper (address at index.android.bundle:1:2747690) at construct (native) at _createSuperInternal (address at index.android.bundle:1:2746826) at call (native) at JoplinError (address at index.android.bundle:1:2747154) at ?anon0 (address at index.android.bundle:1:3033348) at next (native) at fulfilled (address at index.android.bundle:1:3029007) at tryCallOne (address at InternalBytecode.js:1:1180) at anonymous (address at InternalBytecode.js:1:1874) at apply (native) at anonymous (address at index.android.bundle:1:286591) at _callTimer (address at index.android.bundle:1:285542) at _callReactNativeMicrotasksPass (address at index.android.bundle:1:285686) at callReactNativeMicrotasks (address at index.android.bundle:1:287676) at callReactNativeMicrotasks (address at index.android.bundle:1:148328) at anonymous (address at index.android.bundle:1:147412) at guard (address at index.android.bundle:1:148166) at flushedQueue (address at index.android.bundle:1:147323) at invokeCallbackAndReturnFlushedQueue (address at index.android.bundle:1:147266) 08-25T13:31:42: JoplinServerApi: curl -v -X GET -H "X-API-AUTH: **" -H "X-API-MIN-VERSION: 2.6.0" 'https://api.joplincloud.com/api/items/root:/:/delta?cursor=Qv3k9hQUfntkQGqBtGVy0L' 08-25T13:31:42: JoplinServerApi: Code: 08-25T13:31:42: JoplinServerApi: TypeError: Network request failed TypeError: Network request failed at anonymous (address at index.android.bundle:1:318538) at apply (native) at anonymous (address at index.android.bundle:1:286244) at _callTimer (address at index.android.bundle:1:285542) at callTimers (address at index.android.bundle:1:287310) at apply (native) at callFunction (address at index.android.bundle:1:148905) at anonymous (address at index.android.bundle:1:147210) at guard (address at index.android.bundle:1:148166) at callFunctionReturnFlushedQueue (address at index.android.bundle:1:147168) 08-25T13:31:42: JoplinServerApi: TypeError: Network request failed TypeError: Network request failed at anonymous (address at index.android.bundle:1:318538) at apply (native) at anonymous (address at index.android.bundle:1:286244) at _callTimer (address at index.android.bundle:1:285542) at callTimers (address at index.android.bundle:1:287310) at apply (native) at callFunction (address at index.android.bundle:1:148905) at anonymous (address at index.android.bundle:1:147210) at guard (address at index.android.bundle:1:148166) at callFunctionReturnFlushedQueue (address at index.android.bundle:1:147168) 08-25T13:31:42: JoplinServerApi: curl -v -X GET -H "X-API-AUTH: **" -H "X-API-MIN-VERSION: 2.6.0" 'https://api.joplincloud.com/api/locks' 08-25T13:31:42: JoplinServerApi: Code: 08-25T13:31:42: JoplinServerApi: TypeError: Network request failed TypeError: Network request failed at anonymous (address at index.android.bundle:1:318538) at apply (native) at anonymous (address at index.android.bundle:1:286244) at _callTimer (address at index.android.bundle:1:285542) at callTimers (address at index.android.bundle:1:287310) at apply (native) at callFunction (address at index.android.bundle:1:148905) at anonymous (address at index.android.bundle:1:147210) at guard (address at index.android.bundle:1:148166) at callFunctionReturnFlushedQueue (address at index.android.bundle:1:147168) 08-25T13:31:42: JoplinServerApi: curl -v -X GET -H "X-API-AUTH: **" -H "X-API-MIN-VERSION: 2.6.0" 'https://api.joplincloud.com/api/items/root:/bf786195fca9434187aa265a6930d0e2.md:/content' 08-25T13:31:42: JoplinServerApi: Code: 08-25T13:31:42: JoplinServerApi: TypeError: Network request failed TypeError: Network request failed at anonymous (address at index.android.bundle:1:318538) at apply (native) at anonymous (address at index.android.bundle:1:286244) at _callTimer (address at index.android.bundle:1:285542) at callTimers (address at index.android.bundle:1:287310) at apply (native) at callFunction (address at index.android.bundle:1:148905) at anonymous (address at index.android.bundle:1:147210) at guard (address at index.android.bundle:1:148166) at callFunctionReturnFlushedQueue (address at index.android.bundle:1:147168) 08-25T13:31:42: JoplinServerApi: curl -v -X GET -H "X-API-AUTH: **" -H "X-API-MIN-VERSION: 2.6.0" 'https://api.joplincloud.com/api/items/root:/0f291800816140f2b16426489834b375.md:/content' 08-25T13:31:42: JoplinServerApi: Code: 08-25T13:31:42: JoplinServerApi: curl -v -X GET -H "X-API-AUTH: **" -H "X-API-MIN-VERSION: 2.6.0" 'https://api.joplincloud.com/api/items/root:/89cb0fdae9b546369325a2d7c7e0fe4d.md:/content' 08-25T13:31:42: JoplinServerApi: Code: 08-25T13:31:42: JoplinServerApi: TypeError: Network request failed TypeError: Network request failed at anonymous (address at index.android.bundle:1:318538) at apply (native) at anonymous (address at index.android.bundle:1:286244) at _callTimer (address at index.android.bundle:1:285542) at callTimers (address at index.android.bundle:1:287310) at apply (native) at callFunction (address at index.android.bundle:1:148905) at anonymous (address at index.android.bundle:1:147210) at guard (address at index.android.bundle:1:148166) at callFunctionReturnFlushedQueue (address at index.android.bundle:1:147168) 08-25T13:31:42: JoplinServerApi: TypeError: Network request failed TypeError: Network request failed at anonymous (address at index.android.bundle:1:318538) at apply (native) at anonymous (address at index.android.bundle:1:286244) at _callTimer (address at index.android.bundle:1:285542) at callTimers (address at index.android.bundle:1:287310) at apply (native) at callFunction (address at index.android.bundle:1:148905) at anonymous (address at index.android.bundle:1:147210) at guard (address at index.android.bundle:1:148166) at callFunctionReturnFlushedQueue (address at index.android.bundle:1:147168) 08-25T13:31:42: JoplinServerApi: curl -v -X GET -H "X-API-AUTH: **" -H "X-API-MIN-VERSION: 2.6.0" 'https://api.joplincloud.com/api/items/root:/0e1b46c6b9c94806923e5cc81504bca1.md:/content' 08-25T13:31:42: JoplinServerApi: Code: 08-25T13:31:42: JoplinServerApi: curl -v -X GET -H "X-API-AUTH: **" -H "X-API-MIN-VERSION: 2.6.0" 'https://api.joplincloud.com/api/items/root:/219918e041c74cadb324c15e7af78acf.md:/content' 08-25T13:31:42: JoplinServerApi: Code: 08-25T13:31:42: JoplinServerApi: TypeError: Network request failed TypeError: Network request failed at anonymous (address at index.android.bundle:1:318538) at apply (native) at anonymous (address at index.android.bundle:1:286244) at _callTimer (address at index.android.bundle:1:285542) at callTimers (address at index.android.bundle:1:287310) at apply (native) at callFunction (address at index.android.bundle:1:148905) at anonymous (address at index.android.bundle:1:147210) at guard (address at index.android.bundle:1:148166) at callFunctionReturnFlushedQueue (address at index.android.bundle:1:147168) 08-25T13:20:24: e2ee/utils: Cannot load master key 9debb2c0732948deb5339354d93324d5. Invalid password? Error: ccm: tag doesn't match Error: ccm: tag doesn't match at ?anon0 (address at index.android.bundle:1:1511071) at next (native) at anonymous (address at index.android.bundle:1:1505476) at tryCallTwo (address at InternalBytecode.js:1:1222) at doResolve (address at InternalBytecode.js:1:2541) at Promise (address at InternalBytecode.js:1:1318) at anonymous (address at index.android.bundle:1:1505308) at decrypt (address at index.android.bundle:1:1510729) at ?anon0 (address at index.android.bundle:1:1509427) at next (native) at anonymous (address at index.android.bundle:1:1505476) at tryCallTwo (address at InternalBytecode.js:1:1222) at doResolve (address at InternalBytecode.js:1:2541) at Promise (address at InternalBytecode.js:1:1318) at anonymous (address at index.android.bundle:1:1505308) at decryptMasterKeyContent (address at index.android.bundle:1:1509328) at ?anon0 (address at index.android.bundle:1:1507351) at next (native) at anonymous (address at index.android.bundle:1:1505476) at tryCallTwo (address at InternalBytecode.js:1:1222) at doResolve (address at InternalBytecode.js:1:2541) at Promise (address at InternalBytecode.js:1:1318) at anonymous (address at index.android.bundle:1:1505308) at loadMasterKey (address at index.android.bundle:1:1507187) at ?anon0 (address at index.android.bundle:1:2974217) at next (native) at fulfilled (address at index.android.bundle:1:2977966) at tryCallOne (address at InternalBytecode.js:1:1180) at anonymous (address at InternalBytecode.js:1:1874) at apply (native) at anonymous (address at index.android.bundle:1:286591) at _callTimer (address at index.android.bundle:1:285542) at _callReactNativeMicrotasksPass (address at index.android.bundle:1:285686) at callReactNativeMicrotasks (address at index.android.bundle:1:287676) at callReactNativeMicrotasks (address at index.android.bundle:1:148328) at anonymous (address at index.android.bundle:1:147412) at guard (address at index.android.bundle:1:148166) at flushedQueue (address at index.android.bundle:1:147323) at callFunctionReturnFlushedQueue (address at index.android.bundle:1:147179) 08-25T13:20:24: e2ee/utils: Cannot load master key 9debb2c0732948deb5339354d93324d5. Invalid password? Error: ccm: tag doesn't match Error: ccm: tag doesn't match at ?anon0 (address at index.android.bundle:1:1511071) at next (native) at anonymous (address at index.android.bundle:1:1505476) at tryCallTwo (address at InternalBytecode.js:1:1222) at doResolve (address at InternalBytecode.js:1:2541) at Promise (address at InternalBytecode.js:1:1318) at anonymous (address at index.android.bundle:1:1505308) at decrypt (address at index.android.bundle:1:1510729) at ?anon0 (address at index.android.bundle:1:1509427) at next (native) at anonymous (address at index.android.bundle:1:1505476) at tryCallTwo (address at InternalBytecode.js:1:1222) at doResolve (address at InternalBytecode.js:1:2541) at Promise (address at InternalBytecode.js:1:1318) at anonymous (address at index.android.bundle:1:1505308) at decryptMasterKeyContent (address at index.android.bundle:1:1509328) at ?anon0 (address at index.android.bundle:1:1507351) at next (native) at anonymous (address at index.android.bundle:1:1505476) at tryCallTwo (address at InternalBytecode.js:1:1222) at doResolve (address at InternalBytecode.js:1:2541) at Promise (address at InternalBytecode.js:1:1318) at anonymous (address at index.android.bundle:1:1505308) at loadMasterKey (address at index.android.bundle:1:1507187) at ?anon0 (address at index.android.bundle:1:2974217) at next (native) at fulfilled (address at index.android.bundle:1:2977966) at tryCallOne (address at InternalBytecode.js:1:1180) at anonymous (address at InternalBytecode.js:1:1874) at apply (native) at anonymous (address at index.android.bundle:1:286591) at _callTimer (address at index.android.bundle:1:285542) at _callReactNativeMicrotasksPass (address at index.android.bundle:1:285686) at callReactNativeMicrotasks (address at index.android.bundle:1:287676) at callReactNativeMicrotasks (address at index.android.bundle:1:148328) at anonymous (address at index.android.bundle:1:147412) at guard (address at index.android.bundle:1:148166) at flushedQueue (address at index.android.bundle:1:147323) at callFunctionReturnFlushedQueue (address at index.android.bundle:1:147179) 08-25T13:19:06: Synchronizer: Could not refresh lock - cancelling sync. Error was: Error: Lock has expired Code: lockExpired Error: Lock has expired at construct (native) at Wrapper (address at index.android.bundle:1:2747690) at construct (native) at _createSuperInternal (address at index.android.bundle:1:2746826) at call (native) at JoplinError (address at index.android.bundle:1:2747154) at ?anon0 (address at index.android.bundle:1:3033348) at next (native) at fulfilled (address at index.android.bundle:1:3029007) at tryCallOne (address at InternalBytecode.js:1:1180) at anonymous (address at InternalBytecode.js:1:1874) at apply (native) at anonymous (address at index.android.bundle:1:286591) at _callTimer (address at index.android.bundle:1:285542) at _callReactNativeMicrotasksPass (address at index.android.bundle:1:285686) at callReactNativeMicrotasks (address at index.android.bundle:1:287676) at callReactNativeMicrotasks (address at index.android.bundle:1:148328) at anonymous (address at index.android.bundle:1:147412) at guard (address at index.android.bundle:1:148166) at flushedQueue (address at index.android.bundle:1:147323) at invokeCallbackAndReturnFlushedQueue (address at index.android.bundle:1:147266) 08-25T13:13:28: Synchronizer: Could not refresh lock - cancelling sync. Error was: Error: Lock has expired Code: lockExpired Error: Lock has expired at construct (native) at Wrapper (address at index.android.bundle:1:2747690) at construct (native) at _createSuperInternal (address at index.android.bundle:1:2746826) at call (native) at JoplinError (address at index.android.bundle:1:2747154) at ?anon0 (address at index.android.bundle:1:3033348) at next (native) at fulfilled (address at index.android.bundle:1:3029007) at tryCallOne (address at InternalBytecode.js:1:1180) at anonymous (address at InternalBytecode.js:1:1874) at apply (native) at anonymous (address at index.android.bundle:1:286591) at _callTimer (address at index.android.bundle:1:285542) at _callReactNativeMicrotasksPass (address at index.android.bundle:1:285686) at callReactNativeMicrotasks (address at index.android.bundle:1:287676) at callReactNativeMicrotasks (address at index.android.bundle:1:148328) at anonymous (address at index.android.bundle:1:147412) at guard (address at index.android.bundle:1:148166) at flushedQueue (address at index.android.bundle:1:147323) at invokeCallbackAndReturnFlushedQueue (address at index.android.bundle:1:147266) 08-25T13:11:06: JoplinServerApi: curl -v -X GET -H "X-API-AUTH: **" -H "X-API-MIN-VERSION: 2.6.0" 'https://api.joplincloud.com/api/locks' 08-25T13:11:06: JoplinServerApi: Code: 08-25T13:11:06: JoplinServerApi: TypeError: Network request failed TypeError: Network request failed at anonymous (address at index.android.bundle:1:318538) at apply (native) at anonymous (address at index.android.bundle:1:286244) at _callTimer (address at index.android.bundle:1:285542) at callTimers (address at index.android.bundle:1:287310) at apply (native) at callFunction (address at index.android.bundle:1:148905) at anonymous (address at index.android.bundle:1:147210) at guard (address at index.android.bundle:1:148166) at callFunctionReturnFlushedQueue (address at index.android.bundle:1:147168)

github-actions[bot] commented 1 month ago

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? If you require support or are requesting an enhancement or feature then please create a topic on the Joplin forum. This issue may be closed if no further activity occurs. You may comment on the issue and I will leave it open. Thank you for your contributions.

victor03303 commented 1 month ago

this matter has not been resolved in fact, the situation became worse in my case now some items cannot be decrypted anymore, while all of my other devices do just that image

Captain-Barge commented 1 month ago

This issue did not get resolved for me either, however I found a "hacky" workaround: I exported all of my notes to a backup file on desktop, sent it to my phone, put my phone in airplane mode, imported the backup, deleted all of the duplicate notes which resulted (because the phone was partway synced), turned off airplane mode, synced, then switched to desktop and synced.

In the syncing process a lot of notes were unnecessarily deleted and replaced with exact copies. So it wasn't elegant, but it got the job done.

victor03303 commented 1 month ago

When you remove apps from the ipad, it deletes user data as well. So i deleted the app, and synchronized everything again and that made the issue dissapear

victor03303 commented 1 month ago

This issue did not get resolved for me either, however I found a "hacky" workaround: I exported all of my notes to a backup file on desktop, sent it to my phone, put my phone in airplane mode, imported the backup, deleted all of the duplicate notes which resulted (because the phone was partway synced), turned off airplane mode, synced, then switched to desktop and synced.

In the syncing process a lot of notes were unnecessarily deleted and replaced with exact copies. So it wasn't elegant, but it got the job done.

thank you for the inspiration