Argument has been deleted

My company obtained some Lotus Notes databases that we have been asked to process, by going through all the documents in the databases and giving them sets of data from the documents. When we attempt to process them, we run into errors when we are stepping through the documents.

We are trying to access the databases through our own dummy profile, so I’m guessing we’re using the database’s -Default- ACL settings, which is, according to NotesPeek:

name “-Default-”

access-level NoAccess

flags NoDelete PublicReader

Here is example code (written in VB6):

'-------------------------------------------------------

Dim session As Domino.NotesSession

Dim database As Domino.NotesDatabase

Dim docarray As Domino.NotesDocumentCollection

Dim document As Domino.NotesDocument

Dim i As Long

Set session = New Domino.NotesSession

session.Initialize 'no username, no password

Set database = session.GetDatabase(vbNullString, “C:\problemNSF.nsf”) 'not on a server, file is local

If Not database.IsOpen Then Err.Raise -1, “Database is not open”

Set docArray = database.Search(“SELECT @ALL”, Nothing, 0) 'Get all the documents in the database

If docArray.Count = 0 Then Err.Raise -1, “No documents found”

Set document = docArray.GetFirstDocument()

For i = 1 To docArray.Count

Debug.Print document.UniversalID

Set document = docArray.GetNextDocument(document) '<--- ERROR : Argument has been deleted

Next

'-------------------------------------------------------

On the line where I have the error comment, partway through execution do I get that “Argument has been deleted” error, on that line, and when I look at the document object, some of it’s properties are:

Created = #12:00:00 AM#

IsDeleted = False

IsValid = False

LastModified = #12:00:00 AM#

NoteID = “”

NotesURL = “notes: ///__40DE593A16FB0445.nsf/0/000800006000D2140000001400000013?OpenDocument”

UniversalID = “”

For the NotesURL, I changed the replica ID posted, but it is an actual NotesURL (the replica ID is valid), but when I try to run it to open the document, I get “The document specified by the link cannot be located within the linked-to database,” and the UniversalID specified in the NotesURL didn’t exist in the database, even as a deletion stub.

I also tried changing it so at the point I had the error, I’d call GetNthDocument and specify an index higher than where I was, but each call would always return the same document object that seemed to point to some nonexistant document.

And in the Lotus Notes client itself, I can only actually see a dozen documents in the database’s InBox. I can’t even see the All Documents view to try and check that, and the view ($All) doesn’t exist in the backend either. I believe it is not a problem with all the documents themselves, as I can see every document in the database through NotesPeek, but is there any way to skip that problem point or not retrieve that document or to have Notes rebuild it or anything?

Thank you for your help.

EDIT: Problem seems to be ACL related. I used a bit of code found here ( http://www.codestore.net/store.nsf/unid/BLOG-20031110 about halfway down the page, posted by a Ed Wrenbeck), that disables Uniform Access in a Notes database and I was able to see everything inside the database as well as have the script run without a problem.

Subject: Argument has been deleted

Okay, several points here:

  • First, using a search is a slow process because you are re-searching every documents every time you run your script.

There is no need for a search: try to use a simple db.AllDocuments instead:

Set docArray = database.AllDocuments

  • Second, ALL the documents in a Notes database also includes soft deletions (documents marks for deletion but not actually yet deleted) as well as deletion stubs (documents has been deleted, but a marker remains to instruct replicas to propagate the deletion across all replicas).

In order to process only the real values, you would need to weed out the documents with IsValid = False.

Documents that aren’t valid (deletion stubs for instance) will be seen in an @All search, but cannot be actually used once the document is set. Try to add an if before using it:

If document.IsValid Then

Set document = docArray.GetNextDocument(document)

End if

If the document isn’t valid, simply skip it and process the next one: you won’t be missing any real data.

  • Finaly, i would rather use a:

While not document is nothing

(process document here)

Set document = docArray.GetNextDocument(document)

Wend

instead of a count. You save one variable, and in addition, you save yourself some trouble if the number of documents exceeds your counter’s limit.

hoping this helps,

Nicolas Abesdris

Subject: RE: Argument has been deleted

We’ve tried using db.AllDocuments before, but we’ve had cases where it was missing documents that the Search got (and the documents the Search found weren’t soft deletions or deletion stubs in those cases). The Search call only runs once per database, because the search is to get all documents and obtain the Universal IDs, at which point, any attempt to access the documents calls GetDocumentByUNID.

With these Notes databases, we get the same problem even using db.AllDocuments (same error at the same point). AllDocuments and Search(“SELECT @ALL”) return the same count and set of documents.

And how would I skip a document if it isn’t valid to move to the next? In your example, if the document I am on IS valid, then I can move to the next, but if the one I’m on is NOT valid, what do you do? I can’t call GetNextDocument, as that fails. And I can’t call GetNthDocument and use a higher index as it returns the same “document” as GetNextDocument, and I know I’m not at the end of the document collection, as it’s 7700 documents and I’m only at 550. Once I get to the invalid document, I’m stuck.

EDIT: Problem seems to be ACL related. I used a bit of code found here ( http://www.codestore.net/store.nsf/unid/BLOG-20031110 about halfway down the page, posted by a Ed Wrenbeck), that disables Uniform Access in a Notes database and I was able to see everything inside the database as well as have the script run without a problem.

Subject: try this

As Nicholas points out, using IsValid should allow you to skip the trouble documents.

Set docArray = database.AllDocuments

If docArray.Count = 0 Then Err.Raise -1, “No documents found”

For i = 1 To docArray.Count

Set document = docArray.GetNthDocument(i)

If document.Isvalid Then

Debug.Print document.UniversalID

End if

Next

Subject: RE: try this

The code snippet in my original post was a cut down version that I use, but it worked the same and had the same error as the original application that used it.

And your method did actually seem to let it continue, but the problem is that the database properties (of a different database, the first one I was using I removed) say it had 6400 documents, and like that it would have only gotten 640 of them. But we’d need to give them back 6400.

But, as I edited into my original post and my first reply, it seems the problem is tied to the ACLs being enforced in a way to allow access to some documents but not others. But the error messages thrown don’t seem to suggest that to be the case, which is why I didn’t think to look there first.

But thank you both for trying to help.

EDIT: For completeness, you asked for all the properties of the Document object when the error occured, so here:

Authors : Variant(0 to 0)

  • Authors(0) : “”

ColumnValues : Empty

Created : #12:00:00 AM#

EmbeddedObjects : Empty

EncryptionKeys : Variant(0 to 0)

  • EncryptionKeys(0) : “”

EncryptOnSend : False

FolderReferences : Variant(0 to 0)

  • FolderReferences(0) : “”

FTSearchScore : 0

HasEmbedded : False

HttpURL : “”

IsDeleted : False

IsEncrypted : False

IsNewNote : False

IsProfile : False

IsResponse : False

IsSigned : False

IsUIDocOpen : False

IsValid : False

Items : Empty

Key : “”

LastAccessed : #12:00:00 AM#

LastModified : #12:00:00 AM#

LockHolders : Variant(0 to 0)

  • LockHolders(0) : “”

NameOfProfile : “”

NoteID : “”

NotesURL : “notes: ///__40DE593A16FB0445.nsf/0/000000206000D2140000001400000005?OpenDocument”

ParentDatabase : IDatabase

ParentDocumentUNID : “”

ParentView : Nothing

Responses : Nothing

SaveMessageOnSend : False

SentByAgent : False

Signer : “”

SignOnSend : False

Size : 0

UniversalID : “”

Verifier : “”

Again, I changed the replica ID in the NotesURL, but that’s the whole list of properties as VB6 says the Document Object has. And the ParentDatabase does point to the Notes database in that the script is running against.

Subject: RE: try this

if you don’t have access to the documents then the search would not return them so don’t think it’s an ACL issue. Have you used NotesPeek to see if there are actually 6400 valid documents? Or better yet, ask the person you go the dbs from how many documents you are suppsed to be processing.

Subject: RE: try this

The Lotus Notes client’s Database Properties window says 6,476 Documents.NotesPeek says 6,476 Documents and 13,204 Deletion Stubs. Ytria scanEZ says the same as NotesPeek.

The Database.Search call gives a Document Collection that has a count of 6476. And so does Database.AllDocuments.

I’ve tested changing the ACL option “Enforce a consistent Access Control List across all replicas” to off with the C++ code I linked to in my original post edit, and ran my code again, and I never hit the error. And none of the documents come up with IsValid set to False in that case.

Subject: RE: Argument has been deleted

In your first post, is that ALL of your agent code? If not please post it all. Also, you list some of the document properties for 1 of the failed documents, can you pls post ALL of the properties? Thx!